native: Unlink unix socket paths on drop

This prevents unix sockets from remaining on the system all over the place, and
more closely mirrors the behavior of libuv and windows pipes.
This commit is contained in:
Alex Crichton 2014-04-22 13:21:30 -07:00
parent 92f6b925a9
commit f1fb57a5cc
2 changed files with 31 additions and 1 deletions

View File

@ -232,11 +232,14 @@ impl UnixDatagram {
pub struct UnixListener {
inner: Inner,
path: CString,
}
impl UnixListener {
pub fn bind(addr: &CString) -> IoResult<UnixListener> {
bind(addr, libc::SOCK_STREAM).map(|fd| UnixListener { inner: fd })
bind(addr, libc::SOCK_STREAM).map(|fd| {
UnixListener { inner: fd, path: addr.clone() }
})
}
fn fd(&self) -> fd_t { self.inner.fd }
@ -283,3 +286,14 @@ impl rtio::RtioUnixAcceptor for UnixAcceptor {
self.native_accept().map(|s| ~s as ~rtio::RtioPipe:Send)
}
}
impl Drop for UnixListener {
fn drop(&mut self) {
// Unlink the path to the socket to ensure that it doesn't linger. We're
// careful to unlink the path before we close the file descriptor to
// prevent races where we unlink someone else's path.
unsafe {
let _ = libc::unlink(self.path.with_ref(|p| p));
}
}
}

View File

@ -355,4 +355,20 @@ mod tests {
rx.recv();
})
iotest!(fn drop_removes_listener_path() {
let path = next_test_unix();
let l = UnixListener::bind(&path).unwrap();
assert!(path.exists());
drop(l);
assert!(!path.exists());
} #[cfg(not(windows))])
iotest!(fn drop_removes_acceptor_path() {
let path = next_test_unix();
let l = UnixListener::bind(&path).unwrap();
assert!(path.exists());
drop(l.listen().unwrap());
assert!(!path.exists());
} #[cfg(not(windows))])
}