Skip to content

Commit ab80e7f

Browse files
committed
fix(dbus) make dbus path parth of a CompositeDevice at construction
DBus path cannot be None as part of the code expects it and it will call .unwrap() on the option potentially crashing the software: construct a CompositeDevice with that value in place and ready for every other subsequent usage.
1 parent 86849dc commit ab80e7f

File tree

2 files changed

+63
-91
lines changed

2 files changed

+63
-91
lines changed

src/input/composite_device/mod.rs

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ use std::{
88
};
99

1010
use evdev::InputEvent;
11-
use tokio::{sync::mpsc, task::JoinSet, time::Duration};
11+
use tokio::{
12+
sync::mpsc,
13+
task::{JoinHandle, JoinSet},
14+
time::Duration,
15+
};
1216
use zbus::Connection;
1317

1418
use crate::{
@@ -94,7 +98,7 @@ pub struct CompositeDevice {
9498
/// release events
9599
emitted_mappings: HashMap<String, CapabilityMapping>,
96100
/// The DBus path this [CompositeDevice] is listening on
97-
dbus_path: Option<String>,
101+
dbus_path: String,
98102
/// Mode defining how inputs should be routed
99103
intercept_mode: InterceptMode,
100104
/// Transmit channel for sending commands to this composite device
@@ -157,6 +161,7 @@ impl CompositeDevice {
157161
manager: mpsc::Sender<ManagerCommand>,
158162
config: CompositeDeviceConfig,
159163
device_info: UdevDevice,
164+
dbus_path: String,
160165
capability_map: Option<CapabilityMap>,
161166
) -> Result<Self, Box<dyn Error>> {
162167
log::info!("Creating CompositeDevice with config: {}", config.name);
@@ -175,7 +180,7 @@ impl CompositeDevice {
175180
translatable_active_inputs: Vec::new(),
176181
translated_recent_events: HashSet::new(),
177182
emitted_mappings: HashMap::new(),
178-
dbus_path: None,
183+
dbus_path,
179184
intercept_mode: InterceptMode::None,
180185
tx,
181186
rx,
@@ -231,22 +236,25 @@ impl CompositeDevice {
231236
Ok(device)
232237
}
233238

239+
/// Return the DBus path of the composite device
240+
pub fn dbus_path(&self) -> String {
241+
self.dbus_path.clone()
242+
}
243+
234244
/// Creates a new instance of the composite device interface on DBus.
235-
pub async fn listen_on_dbus(&mut self, path: String) -> Result<(), Box<dyn Error>> {
245+
pub async fn listen_on_dbus(&self) -> Result<JoinHandle<()>, Box<dyn Error>> {
236246
let conn = self.conn.clone();
237247
let client = self.client();
238-
self.dbus_path = Some(path.clone());
239-
tokio::spawn(async move {
248+
let path = self.dbus_path();
249+
Ok(tokio::spawn(async move {
240250
log::debug!("Starting dbus interface: {path}");
241251
let iface = CompositeDeviceInterface::new(client);
242252
if let Err(e) = conn.object_server().at(path.clone(), iface).await {
243253
log::debug!("Failed to start dbus interface {path}: {e:?}");
244254
} else {
245-
log::debug!("Started dbus interface: {path}");
255+
log::debug!("Started listening on dbus interface: {path}");
246256
}
247-
});
248-
log::info!("Started listening on {}", self.dbus_path.as_ref().unwrap());
249-
Ok(())
257+
}))
250258
}
251259

252260
/// Starts the [CompositeDevice] and listens for events from all source
@@ -257,6 +265,8 @@ impl CompositeDevice {
257265
) -> Result<(), Box<dyn Error>> {
258266
log::debug!("Starting composite device");
259267

268+
let dbus_path = self.dbus_path.clone();
269+
260270
// Start all source devices
261271
self.run_source_devices().await?;
262272

@@ -371,8 +381,7 @@ impl CompositeDevice {
371381
}
372382
if self.source_devices_used.is_empty() {
373383
log::debug!(
374-
"No source devices remain. Stopping CompositeDevice {:?}",
375-
self.dbus_path
384+
"No source devices remain. Stopping CompositeDevice {dbus_path}"
376385
);
377386
break 'main;
378387
}
@@ -471,27 +480,18 @@ impl CompositeDevice {
471480
self.set_intercept_activation(activation_caps, target_cap)
472481
}
473482
CompositeCommand::Stop => {
474-
log::debug!(
475-
"Got STOP signal. Stopping CompositeDevice: {:?}",
476-
self.dbus_path
477-
);
483+
log::debug!("Got STOP signal. Stopping CompositeDevice: {dbus_path}");
478484
break 'main;
479485
}
480486
CompositeCommand::Suspend(sender) => {
481-
log::info!(
482-
"Preparing for system suspend for: {}",
483-
self.dbus_path.as_ref().unwrap_or(&"".to_string())
484-
);
487+
log::info!("Preparing for system suspend for: {dbus_path}");
485488
self.handle_suspend().await;
486489
if let Err(e) = sender.send(()).await {
487490
log::error!("Failed to send suspend response: {e:?}");
488491
}
489492
}
490493
CompositeCommand::Resume(sender) => {
491-
log::info!(
492-
"Preparing for system resume for: {}",
493-
self.dbus_path.as_ref().unwrap_or(&"".to_string())
494-
);
494+
log::info!("Preparing for system resume for: {dbus_path}");
495495
self.handle_resume().await;
496496
if let Err(e) = sender.send(()).await {
497497
log::error!("Failed to send resume response: {e:?}");
@@ -503,17 +503,11 @@ impl CompositeDevice {
503503
// If no source devices remain after processing the queue, stop
504504
// the device.
505505
if devices_removed && self.source_devices_used.is_empty() {
506-
log::debug!(
507-
"No source devices remain. Stopping CompositeDevice {:?}",
508-
self.dbus_path
509-
);
506+
log::debug!("No source devices remain. Stopping CompositeDevice {dbus_path}");
510507
break 'main;
511508
}
512509
}
513-
log::info!(
514-
"CompositeDevice stopping: {}",
515-
self.dbus_path.as_ref().unwrap()
516-
);
510+
log::info!("CompositeDevice stopping: {dbus_path}");
517511

518512
// Stop all target devices
519513
log::debug!("Stopping target devices");
@@ -556,10 +550,7 @@ impl CompositeDevice {
556550
res?;
557551
}
558552

559-
log::info!(
560-
"CompositeDevice stopped: {}",
561-
self.dbus_path.as_ref().unwrap()
562-
);
553+
log::info!("CompositeDevice stopped: {dbus_path}");
563554

564555
Ok(())
565556
}
@@ -1800,9 +1791,7 @@ impl CompositeDevice {
18001791
}
18011792
}
18021793

1803-
let Some(composite_path) = self.dbus_path.clone() else {
1804-
return Err("No composite device DBus path found".into());
1805-
};
1794+
let composite_path = self.dbus_path.clone();
18061795

18071796
// Create new target devices using the input manager
18081797
for kind in device_types_to_start {
@@ -1909,6 +1898,8 @@ impl CompositeDevice {
19091898
&mut self,
19101899
targets: HashMap<String, TargetDeviceClient>,
19111900
) -> Result<(), Box<dyn Error>> {
1901+
let dbus_path = self.dbus_path.clone();
1902+
19121903
// Keep track of all target devices
19131904
for (path, target) in targets.into_iter() {
19141905
log::debug!("Attaching target device: {path}");
@@ -1917,10 +1908,7 @@ impl CompositeDevice {
19171908
format!("Failed to set composite device for target device: {:?}", e).into(),
19181909
);
19191910
}
1920-
log::debug!(
1921-
"Attached device {path} to {:?}",
1922-
self.dbus_path.as_ref().unwrap_or(&"".to_string())
1923-
);
1911+
log::debug!("Attached device {path} to {dbus_path}");
19241912

19251913
// Query the target device for its capabilities
19261914
let caps = match target.get_capabilities().await {
@@ -1956,10 +1944,7 @@ impl CompositeDevice {
19561944

19571945
/// Emit a DBus signal when target devices change
19581946
async fn signal_targets_changed(&self) {
1959-
let Some(dbus_path) = self.dbus_path.clone() else {
1960-
log::error!("No DBus path for composite device exists to emit signal!");
1961-
return;
1962-
};
1947+
let dbus_path = self.dbus_path.clone();
19631948
let conn = self.conn.clone();
19641949

19651950
tokio::task::spawn(async move {
@@ -1991,10 +1976,7 @@ impl CompositeDevice {
19911976

19921977
/// Emit a DBus signal when source devices change
19931978
async fn signal_sources_changed(&self) {
1994-
let Some(dbus_path) = self.dbus_path.clone() else {
1995-
log::error!("No DBus path for composite device exists to emit signal!");
1996-
return;
1997-
};
1979+
let dbus_path = self.dbus_path.clone();
19981980
let conn = self.conn.clone();
19991981

20001982
tokio::task::spawn(async move {

src/input/manager.rs

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use mio::{Events, Interest, Poll, Token};
1010
use thiserror::Error;
1111
use tokio::sync::mpsc;
1212
use tokio::task;
13+
use tokio::task::JoinHandle;
1314
use zbus::fdo::ManagedObjects;
1415
use zbus::zvariant::ObjectPath;
1516
use zbus::Connection;
@@ -467,6 +468,7 @@ impl Manager {
467468
self.tx.clone(),
468469
config,
469470
device,
471+
self.next_composite_dbus_path()?,
470472
capability_map,
471473
)?;
472474

@@ -580,22 +582,19 @@ impl Manager {
580582
config: CompositeDeviceConfig,
581583
target_types: Option<Vec<String>>,
582584
source_device: SourceDevice,
583-
) -> Result<(), Box<dyn Error>> {
584-
// Generate the DBus tree path for this composite device
585-
let path = self.next_composite_dbus_path();
586-
585+
) -> Result<JoinHandle<()>, Box<dyn Error>> {
587586
// Keep track of the source devices that this composite device is
588587
// using.
589588
let source_device_ids = device.get_source_devices_used();
589+
let composite_path = device.dbus_path();
590590
log::debug!(
591-
"Starting CompositeDevice at {path} with the following sources: {source_device_ids:?}"
591+
"Starting CompositeDevice at {composite_path} with the following sources: {source_device_ids:?}"
592592
);
593593
for id in source_device_ids {
594-
self.source_devices_used.insert(id.clone(), path.clone());
594+
self.source_devices_used.insert(id.clone(), composite_path.clone());
595595
self.source_devices.insert(id, source_device.clone());
596596
}
597597

598-
let composite_path = path.clone();
599598
if !self.composite_device_sources.contains_key(&composite_path) {
600599
self.composite_device_sources
601600
.insert(composite_path.clone(), Vec::new());
@@ -606,8 +605,7 @@ impl Manager {
606605
.unwrap();
607606
sources.push(source_device);
608607

609-
// Create a DBus interface for the device
610-
device.listen_on_dbus(path.clone()).await?;
608+
device.listen_on_dbus().await?;
611609

612610
// Get a handle to the device
613611
let client = device.client();
@@ -616,7 +614,7 @@ impl Manager {
616614
let mut target_device_paths = Vec::new();
617615

618616
// Create a DBus target device
619-
log::debug!("Creating target devices for {path}");
617+
log::debug!("Creating target devices for {composite_path}");
620618
let dbus_device = self.create_target_device("dbus").await?;
621619
let dbus_devices = self.start_target_devices(vec![dbus_device]).await?;
622620
let dbus_paths = dbus_devices.keys();
@@ -641,33 +639,30 @@ impl Manager {
641639
target_device_paths.push(target_path.clone());
642640
}
643641

642+
// Add the device to our maps
643+
self.composite_devices.insert(device.dbus_path(), client);
644+
log::trace!("Managed source devices: {:?}", self.source_devices_used);
645+
self.used_configs.insert(composite_path.clone(), config);
646+
log::trace!("Used configs: {:?}", self.used_configs);
647+
self.composite_device_targets
648+
.insert(composite_path.clone(), target_device_paths);
649+
log::trace!("Used target devices: {:?}", self.composite_device_targets);
650+
644651
// Run the device
645-
let dbus_path = path.clone();
652+
let composite_path = device.dbus_path();
646653
let tx = self.tx.clone();
647-
tokio::spawn(async move {
654+
Ok(tokio::spawn(async move {
648655
if let Err(e) = device.run(targets).await {
649-
log::error!("Error running {dbus_path}: {e}");
656+
log::error!("Error running {composite_path}: {}", e.to_string());
650657
}
651-
log::debug!("Composite device stopped running: {dbus_path}");
658+
log::debug!("Composite device stopped running: {composite_path}");
652659
if let Err(e) = tx
653-
.send(ManagerCommand::CompositeDeviceStopped(dbus_path))
660+
.send(ManagerCommand::CompositeDeviceStopped(composite_path.clone()))
654661
.await
655662
{
656-
log::error!("Error sending composite device stopped: {e}");
663+
log::error!("Error sending to composite device {composite_path} the stopped signal: {}", e.to_string());
657664
}
658-
});
659-
let comp_path = path.clone();
660-
661-
// Add the device to our maps
662-
self.composite_devices.insert(comp_path, client);
663-
log::trace!("Managed source devices: {:?}", self.source_devices_used);
664-
self.used_configs.insert(path, config);
665-
log::trace!("Used configs: {:?}", self.used_configs);
666-
self.composite_device_targets
667-
.insert(composite_path.clone(), target_device_paths);
668-
log::trace!("Used target devices: {:?}", self.composite_device_targets);
669-
670-
Ok(())
665+
}))
671666
}
672667

673668
/// Called when a composite device stops running
@@ -1275,20 +1270,15 @@ impl Manager {
12751270
}
12761271

12771272
/// Returns the next available composite device dbus path
1278-
fn next_composite_dbus_path(&self) -> String {
1279-
let max = 2048;
1280-
let mut i = 0;
1281-
loop {
1282-
if i > max {
1283-
return "Devices exceeded".to_string();
1284-
}
1273+
fn next_composite_dbus_path(&self) -> Result<String, Box<dyn Error>> {
1274+
for i in 0u64.. {
12851275
let path = format!("{}/CompositeDevice{}", BUS_PREFIX, i);
1286-
if self.composite_devices.contains_key(&path) {
1287-
i += 1;
1288-
continue;
1276+
if !self.composite_devices.contains_key(&path) {
1277+
return Ok(path)
12891278
}
1290-
return path;
12911279
}
1280+
1281+
Err(Box::from("No available dbus path left"))
12921282
}
12931283

12941284
/// Watch for IIO device events

0 commit comments

Comments
 (0)