Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39799535 authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

Floss: Fix deadlock in powerd suspend manager

The deadlock occurs when self.context.lock() is called inside an `if
let` block that also holds the guard of self.context.lock(). To solve
this we should lock only once and then we can use the guarded
self.context multiple times in an anonymous block.

Bug: 233562909
Tag: #floss
Test: Manual - powerd_dbus_suspend when Floss is not enabled

Change-Id: I2f7f1a40dd74fb5e1bcdfa6df97e23dab9a0a3b5
parent b4a88c7d
Loading
Loading
Loading
Loading
+24 −19
Original line number Diff line number Diff line
@@ -428,7 +428,11 @@ impl PowerdSuspendManager {

        self.context.lock().unwrap().pending_suspend_imminent = Some(suspend_imminent.clone());

        if let Some(adapter_suspend_dbus) = &self.context.lock().unwrap().adapter_suspend_dbus {
        {
            // Anonymous block to contain locked `self.context` which needs to be called multiple
            // times in the `if let` block below. Prevent deadlock by locking only once.
            let context_locked = self.context.lock().unwrap();
            if let Some(adapter_suspend_dbus) = &context_locked.adapter_suspend_dbus {
                let adapter_suspend_id =
                    adapter_suspend_dbus.suspend(match suspend_imminent.get_reason() {
                        SuspendImminent_Reason::IDLE => SuspendType::Connected,
@@ -437,10 +441,10 @@ impl PowerdSuspendManager {
                    });
                log::debug!("Adapter suspend id = {}", adapter_suspend_id);
            } else {
            // If there is no adapter, that means Bluetooth is not active and we should always tell
            // powerd that we are ready to suspend.
                // If there is no adapter, that means Bluetooth is not active and we should always
                // tell powerd that we are ready to suspend.
                log::debug!("Adapter not available, suspend is ready.");
            if let Some(session) = &self.context.lock().unwrap().powerd_session {
                if let Some(session) = &context_locked.powerd_session {
                    send_handle_suspend_readiness(
                        session.powerd_proxy.clone(),
                        session.delay_id,
@@ -451,6 +455,7 @@ impl PowerdSuspendManager {
                }
            }
        }
    }

    fn on_suspend_done(&mut self, suspend_done: SuspendDone) {
        // powerd is telling us that suspend is done (system has resumed), so we tell btadapterd