diff --git a/Cargo.lock b/Cargo.lock index b85990f..6e86151 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "autocfg" version = "0.1.1" diff --git a/src/bluez/adapter/mod.rs b/src/bluez/adapter/mod.rs index 54e707e..636ea45 100644 --- a/src/bluez/adapter/mod.rs +++ b/src/bluez/adapter/mod.rs @@ -175,6 +175,7 @@ pub struct ConnectedAdapter { peripherals: Arc>>, handle_map: Arc>>, event_handlers: Arc>>, + do_cleanup: bool, } impl ConnectedAdapter { @@ -206,6 +207,7 @@ impl ConnectedAdapter { event_handlers: Arc::new(Mutex::new(vec![])), peripherals: Arc::new(Mutex::new(HashMap::new())), handle_map: Arc::new(Mutex::new(HashMap::new())), + do_cleanup: true, }; connected.add_raw_socket_reader(adapter_fd); @@ -215,6 +217,16 @@ impl ConnectedAdapter { Ok(connected) } + /// If keep, don't close the backing file descriptor when this ConnectedAdapter goes + /// out of scope. If all ConnectedAdapters referencing a given socket file descriptor + /// are told to keep_fd, this will leak file descriptors. + /// + /// For threaded use, clone a ConnectedAdapter whose lifetime is longer than the + /// thread's lifetime, and set the thread's clone to keep_fd. + pub unsafe fn keep_fd(&mut self, keep: bool) { + self.do_cleanup = !keep; + } + fn set_socket_filter(&self) -> Result<()> { let mut filter = BytesMut::with_capacity(14); let type_mask = (1 << HCI_COMMAND_PKT) | (1 << HCI_EVENT_PKT) | (1 << HCI_ACLDATA_PKT); @@ -432,6 +444,23 @@ impl Central for ConnectedAdapter { } } +impl Drop for ConnectedAdapter { + fn drop(&mut self) { + if self.do_cleanup { + return; + } + + self.should_stop.store(true, Ordering::Relaxed); + + // there are a bunch of things with a reference to this file + // descriptor, so the first one will close it and the rest will + // return EBADF. + handle_error(unsafe { + libc::close(self.adapter_fd) + }).ok(); + } +} + /// Adapter represents a physical bluetooth interface in your system, for example a bluetooth /// dongle. #[derive(Debug, Clone)]