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

Commit 753429ca authored by Archie Pusaka's avatar Archie Pusaka
Browse files

floss: Shutdown DBus connection to prevent sysprops crash

It is possible to receive a DBus message when the adapter is disabled.
At this point, the stack manager and related threads have been stopped,
and the sysprop module has been shut down. Therefore, calling sysprop
via DBus, e.g. by BluetoothGatt.StartScan, might crash.

This CL prevents the crash by shutting down DBus connection before
disabling the adapter.

Bug: 308506915
Test: m -j
Test: Spam the following dbus message while powering off/on bluetooth
      via UI. Verify there is no crash.
      dbus-send --system --print-reply --dest=org.chromium.bluetooth \
      /org/chromium/bluetooth/hci0/gatt \
      org.chromium.bluetooth.BluetoothGatt.StartScan \
      byte:1 array:byte: array:byte:

Flag: EXEMPT floss only change

Change-Id: Ib6905bc24ec2584bb85c924b754531f8877b800b
parent b2d30d48
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ use btstack::{
    battery_service::BatteryService, bluetooth::Bluetooth, bluetooth_admin::BluetoothAdmin,
    bluetooth_gatt::BluetoothGatt, bluetooth_logging::BluetoothLogging,
    bluetooth_media::BluetoothMedia, bluetooth_qa::BluetoothQA,
    socket_manager::BluetoothSocketManager, suspend::Suspend, APIMessage, BluetoothAPI,
    socket_manager::BluetoothSocketManager, suspend::Suspend, APIMessage, BluetoothAPI, Message,
};

use crate::iface_battery_manager;
@@ -35,10 +35,25 @@ impl InterfaceManager {
        channel::<APIMessage>(1)
    }

    /// Runs the dispatch loop for APIMessage
    ///
    /// # Arguments
    ///
    /// * `rx` - The receiver channel for APIMessage
    /// * `tx` - The sender channel for Message
    /// * `virt_index` - The virtual index of the adapter
    /// * `conn` - The DBus connection
    /// * `conn_join_handle` - The thread handle that's maintaining the DBus resource
    /// * `disconnect_watcher` - DisconnectWatcher to monitor client disconnects
    /// * `bluetooth` - Implementation of the Bluetooth API
    /// other implementations follow.
    ///
    pub async fn dispatch(
        mut rx: Receiver<APIMessage>,
        tx: Sender<Message>,
        virt_index: i32,
        conn: Arc<SyncConnection>,
        conn_join_handle: tokio::task::JoinHandle<()>,
        disconnect_watcher: Arc<Mutex<DisconnectWatcher>>,
        bluetooth: Arc<Mutex<Box<Bluetooth>>>,
        bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
@@ -233,6 +248,18 @@ impl InterfaceManager {
                        );
                    }
                },

                APIMessage::ShutDown => {
                    // To shut down the connection, call _handle.abort() and drop the connection.
                    conn_join_handle.abort();
                    drop(conn);

                    let tx = tx.clone();
                    tokio::spawn(async move {
                        let _ = tx.send(Message::AdapterShutdown).await;
                    });
                    break;
                }
            }
        }
    }
+6 −3
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ fn main() -> Result<(), Box<dyn Error>> {

        // The `resource` is a task that should be spawned onto a tokio compatible
        // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
        tokio::spawn(async {
        let conn_join_handle = tokio::spawn(async {
            let err = resource.await;
            panic!("Lost connection to D-Bus: {}", err);
        });
@@ -218,6 +218,7 @@ fn main() -> Result<(), Box<dyn Error>> {
        // Run the stack main dispatch loop.
        topstack::get_runtime().spawn(Stack::dispatch(
            rx,
            api_tx.clone(),
            bluetooth.clone(),
            bluetooth_gatt.clone(),
            battery_service.clone(),
@@ -237,8 +238,10 @@ fn main() -> Result<(), Box<dyn Error>> {

        tokio::spawn(interface_manager::InterfaceManager::dispatch(
            api_rx,
            tx.clone(),
            virt_index,
            conn.clone(),
            conn,
            conn_join_handle,
            disconnect_watcher.clone(),
            bluetooth.clone(),
            bluetooth_admin.clone(),
@@ -310,7 +313,7 @@ extern "C" fn handle_sigterm(_signum: i32) {
        let txl = tx.clone();
        tokio::spawn(async move {
            // Send the shutdown message here.
            let _ = txl.send(Message::Shutdown).await;
            let _ = txl.send(Message::InterfaceShutdown).await;
        });

        let guard = notifier.enabled.lock().unwrap();
+18 −3
Original line number Diff line number Diff line
@@ -63,8 +63,11 @@ use bt_topshim::{

/// Message types that are sent to the stack main dispatch loop.
pub enum Message {
    // Shuts down the stack.
    Shutdown,
    /// Remove the DBus API. Call it before other AdapterShutdown.
    InterfaceShutdown,
    /// Disable the adapter by calling btif disable.
    AdapterShutdown,
    /// Clean up the adapter by calling btif cleanup.
    Cleanup,

    // Adapter is enabled and ready.
@@ -164,8 +167,12 @@ pub enum BluetoothAPI {
    Gatt,
}

/// Message types that are sent to the InterfaceManager's dispatch loop.
pub enum APIMessage {
    /// Indicates a subcomponent is ready to receive DBus messages.
    IsReady(BluetoothAPI),
    /// Indicates bluetooth is shutting down, so we remove all DBus endpoints.
    ShutDown,
}

/// Represents suspend mode of a module.
@@ -192,6 +199,7 @@ impl Stack {
    /// Runs the main dispatch loop.
    pub async fn dispatch(
        mut rx: Receiver<Message>,
        api_tx: Sender<APIMessage>,
        bluetooth: Arc<Mutex<Box<Bluetooth>>>,
        bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
        battery_service: Arc<Mutex<Box<BatteryService>>>,
@@ -213,7 +221,14 @@ impl Stack {
            }

            match m.unwrap() {
                Message::Shutdown => {
                Message::InterfaceShutdown => {
                    let tx = api_tx.clone();
                    tokio::spawn(async move {
                        let _ = tx.send(APIMessage::ShutDown).await;
                    });
                }

                Message::AdapterShutdown => {
                    bluetooth.lock().unwrap().disable();
                }