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

Commit ab4519bd authored by Katherine Lai's avatar Katherine Lai
Browse files

floss: listen for thread_event_cb to exit main thread

Instead of listening to adapter state cbs to exit sigterm,
listen to thread event cbs since that signals that the stack has
been cleaned up. Also serialize stack cleanup.

Bug: 293236498
Tag: #floss
Test: mma -j32
Test: turn off adapter and verify stack cleanup via logs
Change-Id: I5c9e320691c4927c9f7d9a517e41132dac83ea4c
parent b51fc4c1
Loading
Loading
Loading
Loading
+25 −5
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ use btstack::{
    battery_manager::BatteryManager,
    battery_provider_manager::BatteryProviderManager,
    battery_service::BatteryService,
    bluetooth::{Bluetooth, IBluetooth},
    bluetooth::{Bluetooth, IBluetooth, SigData},
    bluetooth_admin::BluetoothAdmin,
    bluetooth_gatt::BluetoothGatt,
    bluetooth_logging::BluetoothLogging,
@@ -49,6 +49,8 @@ const ADMIN_SETTINGS_FILE_PATH: &str = "/var/lib/bluetooth/admin_policy.json";
// The maximum ACL disconnect timeout is 3.5s defined by BTA_DM_DISABLE_TIMER_MS
// and BTA_DM_DISABLE_TIMER_RETRIAL_MS
const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000);
// Time bt_stack_manager waits for cleanup
const STACK_CLEANUP_TIMEOUT_MS: Duration = Duration::from_millis(1000);

const VERBOSE_ONLY_LOG_TAGS: &[&str] = &[
    "bt_bta_av", // AV apis
@@ -135,7 +137,12 @@ fn main() -> Result<(), Box<dyn Error>> {
    init_flags.push(String::from("INIT_classic_discovery_only=true"));

    let (tx, rx) = Stack::create_channel();
    let sig_notifier = Arc::new((Mutex::new(false), Condvar::new()));
    let sig_notifier = Arc::new(SigData {
        enabled: Mutex::new(false),
        enabled_notify: Condvar::new(),
        thread_attached: Mutex::new(false),
        thread_notify: Condvar::new(),
    });

    let intf = Arc::new(Mutex::new(get_btinterface().unwrap()));
    let bluetooth_gatt =
@@ -424,7 +431,7 @@ fn main() -> Result<(), Box<dyn Error>> {

lazy_static! {
    /// Data needed for signal handling.
    static ref SIG_DATA: Mutex<Option<(Sender<Message>, Arc<(Mutex<bool>, Condvar)>)>> = Mutex::new(None);
    static ref SIG_DATA: Mutex<Option<(Sender<Message>, Arc<(SigData)>)>> = Mutex::new(None);
}

extern "C" fn handle_sigterm(_signum: i32) {
@@ -437,10 +444,23 @@ extern "C" fn handle_sigterm(_signum: i32) {
            let _ = txl.send(Message::Shutdown).await;
        });

        let guard = notifier.0.lock().unwrap();
        let guard = notifier.enabled.lock().unwrap();
        if *guard {
            log::debug!("Waiting for stack to turn off for {:?}", STACK_TURN_OFF_TIMEOUT_MS);
            let _ = notifier.1.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS);
            let _ = notifier.enabled_notify.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS);
        }

        log::debug!("SIGTERM cleaning up the stack.");
        let txl = tx.clone();
        tokio::spawn(async move {
            // Send the cleanup message here.
            let _ = txl.send(Message::Cleanup).await;
        });

        let guard = notifier.thread_attached.lock().unwrap();
        if *guard {
            log::debug!("Waiting for stack to clean up for {:?}", STACK_CLEANUP_TIMEOUT_MS);
            let _ = notifier.thread_notify.wait_timeout(guard, STACK_CLEANUP_TIMEOUT_MS);
        }
    }

+35 −8
Original line number Diff line number Diff line
@@ -4,8 +4,8 @@ use bt_topshim::btif::{
    BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState,
    BtBondState, BtConnectionDirection, BtConnectionState, BtDeviceType, BtDiscMode,
    BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType, BtScanMode, BtSspVariant, BtState,
    BtStatus, BtTransport, BtVendorProductInfo, DisplayAddress, RawAddress, ToggleableProfile,
    Uuid, Uuid128Bit,
    BtStatus, BtThreadEvent, BtTransport, BtVendorProductInfo, DisplayAddress, RawAddress,
    ToggleableProfile, Uuid, Uuid128Bit,
};
use bt_topshim::{
    metrics,
@@ -382,6 +382,15 @@ impl BluetoothDeviceContext {
    }
}

/// Structure to track all the signals for SIGTERM.
pub struct SigData {
    pub enabled: Mutex<bool>,
    pub enabled_notify: Condvar,

    pub thread_attached: Mutex<bool>,
    pub thread_notify: Condvar,
}

/// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
pub trait IBluetoothCallback: RPCProxy {
    /// When any adapter property changes.
@@ -500,7 +509,7 @@ pub struct Bluetooth {
    discoverable_timeout: Option<JoinHandle<()>>,

    /// Used to notify signal handler that we have turned off the stack.
    sig_notifier: Arc<(Mutex<bool>, Condvar)>,
    sig_notifier: Arc<(SigData)>,
}

impl Bluetooth {
@@ -509,7 +518,7 @@ impl Bluetooth {
        adapter_index: i32,
        hci_index: i32,
        tx: Sender<Message>,
        sig_notifier: Arc<(Mutex<bool>, Condvar)>,
        sig_notifier: Arc<(SigData)>,
        intf: Arc<Mutex<BluetoothInterface>>,
        bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
        bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
@@ -1173,6 +1182,9 @@ pub(crate) trait BtifBluetoothCallbacks {
        min_16_digit: bool,
    ) {
    }

    #[btif_callback(ThreadEvent)]
    fn thread_event(&mut self, event: BtThreadEvent) {}
}

#[btif_callbacks_dispatcher(dispatch_hid_host_callbacks, HHCallbacks)]
@@ -1240,8 +1252,8 @@ impl BtifBluetoothCallbacks for Bluetooth {
                }

                // Let the signal notifier know we are turned off.
                *self.sig_notifier.0.lock().unwrap() = false;
                self.sig_notifier.1.notify_all();
                *self.sig_notifier.enabled.lock().unwrap() = false;
                self.sig_notifier.enabled_notify.notify_all();
            }

            BtState::On => {
@@ -1265,8 +1277,8 @@ impl BtifBluetoothCallbacks for Bluetooth {
                self.set_connectable(true);

                // Notify the signal notifier that we are turned on.
                *self.sig_notifier.0.lock().unwrap() = true;
                self.sig_notifier.1.notify_all();
                *self.sig_notifier.enabled.lock().unwrap() = true;
                self.sig_notifier.enabled_notify.notify_all();

                // Signal that the stack is up and running.
                match self.create_pid_file() {
@@ -1726,6 +1738,21 @@ impl BtifBluetoothCallbacks for Bluetooth {
            None => (),
        };
    }

    fn thread_event(&mut self, event: BtThreadEvent) {
        match event {
            BtThreadEvent::Associate => {
                // Let the signal notifier know stack is initialized.
                *self.sig_notifier.thread_attached.lock().unwrap() = true;
                self.sig_notifier.thread_notify.notify_all();
            }
            BtThreadEvent::Disassociate => {
                // Let the signal notifier know stack is done.
                *self.sig_notifier.thread_attached.lock().unwrap() = false;
                self.sig_notifier.thread_notify.notify_all();
            }
        }
    }
}

struct BleDiscoveryCallbacks {
+4 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ use bt_topshim::{
pub enum Message {
    // Shuts down the stack.
    Shutdown,
    Cleanup,

    // Adapter is enabled and ready.
    AdapterReady,
@@ -196,6 +197,9 @@ impl Stack {
            match m.unwrap() {
                Message::Shutdown => {
                    bluetooth.lock().unwrap().disable();
                }

                Message::Cleanup => {
                    bluetooth.lock().unwrap().cleanup();
                }

+17 −2
Original line number Diff line number Diff line
@@ -329,6 +329,19 @@ impl Into<u32> for BtDiscMode {
    }
}

#[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[repr(u32)]
pub enum BtThreadEvent {
    Associate = 0,
    Disassociate,
}

impl From<bindings::bt_cb_thread_evt> for BtThreadEvent {
    fn from(item: bindings::bt_cb_thread_evt) -> Self {
        BtThreadEvent::from_u32(item).unwrap_or(BtThreadEvent::Associate)
    }
}

#[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[repr(u32)]
pub enum BtIoCap {
@@ -882,8 +895,8 @@ pub enum BaseCallbacks {
        BtConnectionDirection,
        u16,
    ),
    ThreadEvent(BtThreadEvent),
    // Unimplemented so far:
    // thread_evt_cb
    // dut_mode_recv_cb
    // le_test_mode_cb
    // energy_info_cb
@@ -943,6 +956,8 @@ cb_variant!(BaseCb, le_address_associate_cb -> BaseCallbacks::LeAddressAssociate
    let _1 = unsafe { *(_1 as *const RawAddress) };
});

cb_variant!(BaseCb, thread_evt_cb -> BaseCallbacks::ThreadEvent, u32 -> BtThreadEvent);

cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState,
u32 -> BtStatus, *mut RawAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, bindings::bt_conn_direction_t -> BtConnectionDirection, u16 -> u16, {
    let _1 = unsafe { *(_1 as *const RawAddress) };
@@ -1071,7 +1086,7 @@ impl BluetoothInterface {
            address_consolidate_cb: Some(address_consolidate_cb),
            le_address_associate_cb: Some(le_address_associate_cb),
            acl_state_changed_cb: Some(acl_state_cb),
            thread_evt_cb: None,
            thread_evt_cb: Some(thread_evt_cb),
            dut_mode_recv_cb: None,
            le_test_mode_cb: None,
            energy_info_cb: None,