Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Drop for ConnectedAdapter to clean up open sockets #44

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions src/bluez/adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub struct ConnectedAdapter {
peripherals: Arc<Mutex<HashMap<BDAddr, Peripheral>>>,
handle_map: Arc<Mutex<HashMap<u16, BDAddr>>>,
event_handlers: Arc<Mutex<Vec<EventHandler>>>,
do_cleanup: bool,
}

impl ConnectedAdapter {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -432,6 +444,23 @@ impl Central<Peripheral> 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)]
Expand Down