]> git.lizzy.rs Git - rust.git/commitdiff
native: Unlink unix socket paths on drop
authorAlex Crichton <alex@alexcrichton.com>
Tue, 22 Apr 2014 20:21:30 +0000 (13:21 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 22 Apr 2014 20:24:12 +0000 (13:24 -0700)
This prevents unix sockets from remaining on the system all over the place, and
more closely mirrors the behavior of libuv and windows pipes.

src/libnative/io/pipe_unix.rs
src/libstd/io/net/unix.rs

index 22ba643e96a0261e1a4ef14d8f51423bb13c36a3..b332ced1fc5726528b9512f3a88fcd107f3ec783 100644 (file)
@@ -232,11 +232,14 @@ pub fn clone(&mut self) -> 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 @@ fn accept(&mut self) -> IoResult<~rtio::RtioPipe:Send> {
         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));
+        }
+    }
+}
index 6f48abb31c7121358ebfaa742824e66c2d0d7a4b..bf56817702021e8f95c4bcd589a2b580c329de59 100644 (file)
@@ -355,4 +355,20 @@ pub fn smalltest(server: proc(UnixStream):Send, client: proc(UnixStream):Send) {
 
         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))])
 }