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

Commit 2021b1f0 authored by Yun-hao Chung's avatar Yun-hao Chung Committed by Automerger Merge Worker
Browse files

Merge "Floss: Retry socket bind on EINVAL" into main am: 92a4c663

parents e8b46a41 92a4c663
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ regex = "1.5"
serde_json = "1.0"
syslog = "6"
tokio = { version = "1.0", features = ["fs", "macros", "rt-multi-thread", "sync"] }
libc = "0.2"

[build-dependencies]
pkg-config = "0.3.19"
+34 −11
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ use bt_utils::socket::{
    BtSocket, HciChannels, MgmtCommand, MgmtCommandResponse, MgmtEvent, HCI_DEV_NONE,
};

use libc;
use log::{debug, error, info, warn};
use nix::sys::signal::{self, Signal};
use nix::unistd::Pid;
@@ -36,6 +37,10 @@ pub const INDEX_REMOVED_DEBOUNCE_TIME: Duration = Duration::from_millis(150);
/// to avoid dead process + PID not cleaned up from happening.
pub const PID_RUNNING_CHECK_PERIOD: Duration = Duration::from_secs(60);

const HCI_BIND_MAX_RETRY: i32 = 2;

const HCI_BIND_RETRY_INTERVAL: Duration = Duration::from_millis(10);

#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u32)]
pub enum ProcessState {
@@ -362,19 +367,37 @@ fn configure_hci(hci_tx: mpsc::Sender<Message>) {
        x => debug!("Socket open at fd: {}", x),
    }

    tokio::spawn(async move {
        // Bind to control channel (which is used for mgmt commands). We provide
        // HCI_DEV_NONE because we don't actually need a valid HCI dev for some MGMT commands.
        let mut bind_succ = false;
        for _i in 0..HCI_BIND_MAX_RETRY {
            match btsock.bind_channel(HciChannels::Control, HCI_DEV_NONE) {
                -1 => {
            panic!(
                "Failed to bind control channel with errno={}",
                std::io::Error::last_os_error().raw_os_error().unwrap_or(0)
            );
                    match std::io::Error::last_os_error().raw_os_error().unwrap_or(0) {
                        libc::EINVAL => {
                            // If MGMT hasn't been initialized EINVAL will be returned.
                            // Just wait for a short time and try again.
                            debug!("Got EINVAL in bind. Wait and try again");
                            tokio::time::sleep(HCI_BIND_RETRY_INTERVAL).await;
                            continue;
                        }
                        others => {
                            panic!("Failed to bind control channel with errno={}", others);
                        }
                    }
                }
                _ => {
                    bind_succ = true;
                    break;
                }
        _ => (),
            };
        }

        if !bind_succ {
            panic!("bind failed too many times!!");
        }

    tokio::spawn(async move {
        debug!("Spawned hci notify task");

        // Make this into an AsyncFD and start using it for IO