From 2cf8b50a1809dc4c61e03fa2f68f74980a45db02 Mon Sep 17 00:00:00 2001 From: Jay Slater Date: Fri, 7 Feb 2020 16:03:53 -0500 Subject: [PATCH 1/2] Implement Drop for ConnectedAdapter to clean up open sockets --- src/bluez/adapter/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/bluez/adapter/mod.rs b/src/bluez/adapter/mod.rs index 54e707e..521c99b 100644 --- a/src/bluez/adapter/mod.rs +++ b/src/bluez/adapter/mod.rs @@ -432,6 +432,19 @@ impl Central for ConnectedAdapter { } } +impl Drop for ConnectedAdapter { + fn drop(&mut self) { + 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)] From a6ad699f89700cc6a9fe85a67de567054663dffa Mon Sep 17 00:00:00 2001 From: Jay Slater Date: Mon, 10 Feb 2020 11:56:43 -0500 Subject: [PATCH 2/2] Simple fix for clones-going-out-of-scope closing the socket Not a super-satisfying fix, but a fix. --- Cargo.lock | 2 ++ src/bluez/adapter/mod.rs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) 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 521c99b..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); @@ -434,6 +446,10 @@ 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