diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index cdf574e8..14a34be6 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -171,17 +171,19 @@ impl CtrlAnime { loop { // wait for other threads to set not running so we know they exited if !thread_running.load(Ordering::SeqCst) { - thread_exit.store(false, Ordering::SeqCst); info!("AniMe forced a thread to exit"); break; } } + thread_exit.store(false, Ordering::SeqCst); + thread_running.store(true, Ordering::SeqCst); + 'main: loop { - if thread_exit.load(Ordering::SeqCst) { - break 'main; - } for action in actions.iter() { + if thread_exit.load(Ordering::SeqCst) { + break 'main; + } match action { ActionData::Animation(frames) => { if let Err(err) = rog_anime::run_animation( @@ -192,18 +194,14 @@ impl CtrlAnime { .try_lock() .map(|lock| lock.write_data_buffer(frame)) .map_err(|err| { - warn!("rog_anime::run_animation: {}", err); + warn!("rog_anime::run_animation:callback {}", err); AnimeError::NoFrames }) }, ) { - warn!("rog_anime::run_animation: {}", err); + warn!("rog_anime::run_animation:Animation {}", err); break 'main; }; - - if thread_exit.load(Ordering::SeqCst) { - break 'main; - } } ActionData::Image(image) => { once = false; @@ -228,7 +226,6 @@ impl CtrlAnime { lock.write_data_buffer(data); } // Loop ended, set the atmonics - thread_exit.store(false, Ordering::SeqCst); thread_running.store(false, Ordering::SeqCst); info!("AniMe system thread exited"); }) @@ -328,24 +325,30 @@ impl crate::CtrlTask for CtrlAnimeTask { .for_each(|event| { if let Ok(args) = event.args() { if args.start { - if let Ok(lock) = inner.clone().try_lock() { - info!("CtrlAnimeTask running sleep animation"); - lock.thread_exit.store(true, Ordering::Relaxed); - CtrlAnime::run_thread( - inner.clone(), - lock.cache.shutdown.clone(), - true, - ); + loop { + // Loop is required to try an attempt to get the mutex *without* blocking + // other threads - it is possible to end up with deadlocks otherwise. + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running sleep animation"); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.shutdown.clone(), + true, + ); + break; + } } } else { - if let Ok(lock) = inner.clone().try_lock() { - info!("CtrlAnimeTask running wake animation"); - lock.thread_exit.store(true, Ordering::Relaxed); - CtrlAnime::run_thread( - inner.clone(), - lock.cache.wake.clone(), - true, - ); + loop { + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running wake animation"); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.wake.clone(), + true, + ); + break; + } } } } @@ -367,25 +370,29 @@ impl crate::CtrlTask for CtrlAnimeTask { .for_each(|event| { if let Ok(args) = event.args() { if args.start { - if let Ok(lock) = inner.clone().try_lock() { - info!("CtrlAnimeTask running sleep animation"); - lock.thread_exit.store(true, Ordering::Relaxed); - CtrlAnime::run_thread( - inner.clone(), - lock.cache.shutdown.clone(), - true, - ); + loop { + if let Ok(lock) = inner.clone().try_lock() { + info!("CtrlAnimeTask running sleep animation"); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.shutdown.clone(), + true, + ); + break; + } } } else { // If waking up - intention is to catch hibernation event - if let Ok(lock) = inner.clone().try_lock() { - info!("CtrlAnimeTask running wake animation"); - lock.thread_exit.store(true, Ordering::Relaxed); - CtrlAnime::run_thread( - inner.clone(), - lock.cache.wake.clone(), - true, - ); + loop { + if let Ok(lock) = inner.clone().lock() { + info!("CtrlAnimeTask running wake animation"); + CtrlAnime::run_thread( + inner.clone(), + lock.cache.wake.clone(), + true, + ); + break; + } } } } diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index 0558c988..b9e10702 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -111,19 +111,28 @@ impl CtrlTask for CtrlKbdLedTask { // If waking up if !args.start { info!("CtrlKbdLedTask reloading brightness and modes"); - if let Ok(lock) = inner.clone().try_lock() { - lock.set_brightness(lock.config.brightness) + loop { + // Loop so that we do aquire the lock but also don't block other + // threads (prevents potential deadlocks) + if let Ok(lock) = inner.clone().try_lock() { + // Can't reload brightness due to system setting the brightness on sleep/wake + // and the config update task saving that change. + // lock.set_brightness(lock.config.brightness) + // .map_err(|e| error!("CtrlKbdLedTask: {e}")) + // .ok(); + lock.set_side_leds_states( + lock.config.side_leds_enabled, + ) .map_err(|e| error!("CtrlKbdLedTask: {e}")) .ok(); - lock.set_side_leds_states(lock.config.side_leds_enabled) - .map_err(|e| error!("CtrlKbdLedTask: {e}")) - .ok(); - if let Some(mode) = - lock.config.builtins.get(&lock.config.current_mode) - { - lock.write_mode(mode) - .map_err(|e| error!("CtrlKbdLedTask: {e}")) - .ok(); + if let Some(mode) = + lock.config.builtins.get(&lock.config.current_mode) + { + lock.write_mode(mode) + .map_err(|e| error!("CtrlKbdLedTask: {e}")) + .ok(); + } + break; } } } @@ -135,9 +144,10 @@ impl CtrlTask for CtrlKbdLedTask { .detach(); let inner = self.inner.clone(); - self.repeating_task(500, executor, move || { + self.repeating_task(500, executor, move || loop { if let Ok(ref mut lock) = inner.try_lock() { Self::update_config(lock).unwrap(); + break; } }) .await; diff --git a/daemon/src/ctrl_charge.rs b/daemon/src/ctrl_charge.rs index d049b371..31050109 100644 --- a/daemon/src/ctrl_charge.rs +++ b/daemon/src/ctrl_charge.rs @@ -178,13 +178,16 @@ impl CtrlTask for CtrlCharge { // If waking up - intention is to catch hibernation event if !args.start { info!("CtrlCharge reloading charge limit"); - if let Ok(mut lock) = config.clone().try_lock() { - Self::set(lock.bat_charge_limit, &mut lock) - .map_err(|err| { - warn!("CtrlCharge: set_limit {}", err); - err - }) - .ok(); + loop { + if let Ok(mut lock) = config.clone().try_lock() { + Self::set(lock.bat_charge_limit, &mut lock) + .map_err(|err| { + warn!("CtrlCharge: set_limit {}", err); + err + }) + .ok(); + break; + } } } } diff --git a/rog-anime/src/data.rs b/rog-anime/src/data.rs index 1a68f4fe..d745462f 100644 --- a/rog-anime/src/data.rs +++ b/rog-anime/src/data.rs @@ -164,7 +164,7 @@ pub fn run_animation( } } - callback(output)?; + callback(output).ok(); if timed && Instant::now().duration_since(start) > run_time { break 'animation;