Change aura manager task to blocking. Remove idle tasks that keep hanging

This commit is contained in:
Luke D. Jones
2024-03-24 21:14:54 +13:00
parent 739a0ffa63
commit 7eae7c5664
4 changed files with 96 additions and 130 deletions

View File

@@ -28,11 +28,11 @@ version = "6.0.0-alpha1"
rust-version = "1.76" rust-version = "1.76"
[workspace.dependencies] [workspace.dependencies]
tokio = { version = "^1.23.0", default-features = false, features = [ tokio = { version = "^1.36.0", default-features = false, features = [
"macros", "macros",
"sync", "sync",
"time", "time",
"rt", "rt-multi-thread",
] } ] }
concat-idents = "^1.1" concat-idents = "^1.1"
dirs = "^4.0" dirs = "^4.0"

View File

@@ -26,6 +26,7 @@ inotify.workspace = true
mio.workspace = true mio.workspace = true
tokio.workspace = true tokio.workspace = true
# console-subscriber = "0.2.0"
# cli and logging # cli and logging
log.workspace = true log.workspace = true

View File

@@ -5,14 +5,14 @@
// - If udev sees device removed then remove the zbus path // - If udev sees device removed then remove the zbus path
use std::collections::HashSet; use std::collections::HashSet;
use std::sync::Arc; use std::time::Duration;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use mio::{Events, Interest, Poll, Token}; use mio::{Events, Interest, Poll, Token};
use rog_aura::aura_detection::LaptopLedData; use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::AuraDevice; use rog_aura::usb::AuraDevice;
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use tokio::sync::Mutex; use tokio::task::spawn_blocking;
use udev::{Device, MonitorBuilder}; use udev::{Device, MonitorBuilder};
// use zbus::fdo::ObjectManager; // use zbus::fdo::ObjectManager;
use zbus::object_server::SignalContext; use zbus::object_server::SignalContext;
@@ -29,7 +29,7 @@ pub struct AuraManager {
} }
impl AuraManager { impl AuraManager {
pub async fn new(mut connection: Connection) -> Result<Self, RogError> { pub async fn new(connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone(); let conn_copy = connection.clone();
let data = LaptopLedData::get_data(); let data = LaptopLedData::get_data();
let mut interfaces = HashSet::new(); let mut interfaces = HashSet::new();
@@ -42,20 +42,15 @@ impl AuraManager {
let sig_ctx = CtrlAuraZbus::signal_context(&connection)?; let sig_ctx = CtrlAuraZbus::signal_context(&connection)?;
let sig_ctx2 = sig_ctx.clone(); let sig_ctx2 = sig_ctx.clone();
let zbus = CtrlAuraZbus::new(ctrl, sig_ctx); let zbus = CtrlAuraZbus::new(ctrl, sig_ctx);
start_tasks(zbus, &mut connection, sig_ctx2, &path).await?; start_tasks(zbus, connection.clone(), sig_ctx2, path).await?;
} }
// connection.object_server().at("/org/asuslinux",
// ObjectManager).await.unwrap();
let manager = Self { let manager = Self {
_connection: connection, _connection: connection,
}; };
// detect all plugged in aura devices (eventually) // detect all plugged in aura devices (eventually)
let interfaces = Arc::new(Mutex::new(interfaces)); spawn_blocking(move || {
let mut count = 0;
tokio::spawn(async move {
let mut monitor = MonitorBuilder::new()?.match_subsystem("hidraw")?.listen()?; let mut monitor = MonitorBuilder::new()?.match_subsystem("hidraw")?.listen()?;
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
let mut events = Events::with_capacity(1024); let mut events = Events::with_capacity(1024);
@@ -66,135 +61,107 @@ impl AuraManager {
if poll.poll(&mut events, None).is_err() { if poll.poll(&mut events, None).is_err() {
continue; continue;
} }
// collect and sort so remove events are first
// let mut events: Vec<udev::Event> = monitor.iter().filter(|e|
// &*e.action().unwrap_or_default() == "remove").collect();
// let mut adds: Vec<udev::Event> = monitor.iter().filter(|e|
// &*e.action().unwrap_or_default() == "add").collect();
// events.append(&mut adds);
dbg!("LOOPED", count);
count += 1;
for event in monitor.iter() { for event in monitor.iter() {
if event.parent_with_subsystem("hidraw").is_err() { if event.parent_with_subsystem("hidraw").is_err() {
continue; continue;
} }
if let Some(parent) = let parent = if let Some(parent) =
event.parent_with_subsystem_devtype("usb", "usb_device")? event.parent_with_subsystem_devtype("usb", "usb_device")?
{ {
let action = if let Some(action) = event.action() { parent
action } else {
} else { continue;
continue; };
};
let id_product = let action = if let Some(action) = event.action() {
if let Some(id_product) = parent.attribute_value("idProduct") { action
id_product.to_string_lossy() } else {
} else { continue;
continue; };
};
let aura_device = AuraDevice::from(&*id_product); let id_product = if let Some(id_product) = parent.attribute_value("idProduct") {
if aura_device == AuraDevice::Unknown { id_product.to_string_lossy()
warn!("idProduct:{id_product:?} is unknown, not using"); } else {
continue;
};
let path = if let Some(path) = dbus_path_for_dev(&parent) {
path
} else {
continue;
};
let aura_device = AuraDevice::from(&*id_product);
if aura_device == AuraDevice::Unknown {
warn!("idProduct:{id_product:?} is unknown, not using");
continue;
}
if action == "remove" {
if interfaces.remove(&path) {
info!("AuraManager removing: {path:?}");
let conn_copy = conn_copy.clone();
tokio::spawn(async move {
let res = conn_copy
.object_server()
.remove::<CtrlAuraZbus, _>(&path)
.await
.map_err(|e| {
error!("Failed to remove {path:?}, {e:?}");
e
})?;
info!("AuraManager removed: {path:?}, {res}");
Ok::<(), RogError>(())
});
}
} else if action == "add" {
if interfaces.contains(&path) {
debug!("Already a ctrl at {path:?}");
continue; continue;
} }
let path = if let Some(path) = dbus_path_for_dev(&parent) { // Need to check the driver is asus to prevent using hid_generic
path if let Some(p2) = event.parent() {
} else { if let Some(driver) = p2.driver() {
continue; // There is a tree of devices added so filter by driver
}; if driver != "asus" {
debug!("{id_product:?} driver was not asus, skipping");
dbg!(action, &aura_device, &path);
if action == "remove" {
info!("AuraManager removing: {path:?}");
let conn_copy = conn_copy.clone();
let interfaces_copy = interfaces.clone();
tokio::spawn(async move {
let mut interfaces = interfaces_copy.lock().await; // hold until completed
dbg!(&interfaces);
if interfaces.remove(&path) {
let res = conn_copy
.object_server()
.remove::<CtrlAuraZbus, _>(&path)
.await
.map_err(|e| {
error!("Failed to remove {path:?}, {e:?}");
e
})?;
info!("AuraManager removed: {path:?}, {res}");
}
dbg!(&interfaces);
Ok::<(), RogError>(())
});
} else if action == "add" {
if let Some(p2) = event.parent() {
if let Some(driver) = p2.driver() {
// There is a tree of devices added so filter by driver
if driver != "asus" {
debug!("{id_product:?} driver was not asus, skipping");
continue;
}
} else {
continue; continue;
} }
} else {
continue;
} }
}
let path = if let Some(path) = dbus_path_for_dev(&parent) { if let Some(dev_node) = event.devnode() {
path
} else {
continue;
};
let dev_node = if let Some(dev_node) = event.devnode() {
dev_node.to_owned()
} else {
continue;
};
if let Ok(raw) = HidRaw::from_device(event.device()) if let Ok(raw) = HidRaw::from_device(event.device())
.map_err(|e| error!("device path error: {e:?}")) .map_err(|e| error!("device path error: {e:?}"))
{ {
// bah... shitty clone TODO: fix if let Ok(mut ctrl) =
let data_clone = data.clone(); CtrlKbdLed::from_hidraw(raw, path.clone(), &data)
let mut conn_copy = conn_copy.clone(); {
let interfaces_copy = interfaces.clone(); ctrl.config = CtrlKbdLed::init_config(aura_device, &data);
// interfaces.insert(path.clone());
tokio::spawn(async move { info!("AuraManager starting device at: {dev_node:?}, {path:?}");
let mut interfaces = interfaces_copy.lock().await; let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
dbg!(&interfaces); let zbus = CtrlAuraZbus::new(ctrl, sig_ctx);
if interfaces.contains(&path) { let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
debug!("Already a ctrl at {path:?}"); let conn_copy = conn_copy.clone();
return Ok(()); tokio::spawn(async move {
} return tokio::time::timeout(
if let Ok(mut ctrl) = Duration::from_millis(1000),
CtrlKbdLed::from_hidraw(raw, path.clone(), &data_clone) start_tasks(zbus, conn_copy.clone(), sig_ctx, path),
{ )
info!( .await;
"AuraManager found device at: {dev_node:?}, {path:?}" });
); }
debug!("Starting Aura at {path}");
interfaces.insert(path.clone());
let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
ctrl.config =
CtrlKbdLed::init_config(aura_device, &data_clone);
let zbus = CtrlAuraZbus::new(ctrl, sig_ctx);
// Now add it to device list
let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
start_tasks(zbus, &mut conn_copy, sig_ctx, &path).await?;
}
dbg!(&interfaces);
Ok::<(), RogError>(())
}); // Can't get result from here due to
// MonitorSocket
} }
} }
} };
} }
} }
// Required for return type on tokio::spawn // Required for return type on spawn
#[allow(unreachable_code)] #[allow(unreachable_code)]
Ok::<(), RogError>(()) Ok::<(), RogError>(())
}); });
@@ -223,20 +190,17 @@ pub(crate) fn dbus_path_for_dev(parent: &Device) -> Option<OwnedObjectPath> {
async fn start_tasks( async fn start_tasks(
mut zbus: CtrlAuraZbus, mut zbus: CtrlAuraZbus,
connection: &mut Connection, connection: Connection,
signal_ctx: SignalContext<'static>, _signal_ctx: SignalContext<'static>,
path: &ObjectPath<'static>, path: OwnedObjectPath,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
let task = zbus.clone(); // let task = zbus.clone();
// let signal_ctx = signal_ctx.clone();
zbus.reload() zbus.reload()
.await .await
.unwrap_or_else(|err| warn!("Controller error: {}", err)); .unwrap_or_else(|err| warn!("Controller error: {}", err));
connection.object_server().at(path, zbus).await.unwrap();
connection // TODO: skip this until we keep handles to tasks so they can be killed
.object_server() // task.create_tasks(signal_ctx).await
.at(&ObjectPath::from_str_unchecked(path), zbus)
.await
.unwrap();
task.create_tasks(signal_ctx).await.ok();
Ok(()) Ok(())
} }

View File

@@ -18,6 +18,7 @@ use zbus::fdo::ObjectManager;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
// console_subscriber::init();
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
.parse_default_env() .parse_default_env()