From 88900895562e0ab5e0642724fe9dd71eeda79a7a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Jun 2015 09:46:35 -0700 Subject: [PATCH] std: Avoid the WSA_FLAG_NO_HANDLE_INHERIT option This was added after Windows 7 SP1, so it's not always available. Instead use the `SetHandleInformation` function to flag a socket as not inheritable. This is not atomic with respect to creating new processes, but it mirrors what Unix does with respect to possibly using the atomic option in the future. Closes #26543 --- src/libstd/sys/windows/c.rs | 5 ++++ src/libstd/sys/windows/net.rs | 45 ++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 7f89ea979391e..2ddf685729bcb 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -64,6 +64,8 @@ pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD; pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD; +pub const HANDLE_FLAG_INHERIT: libc::DWORD = 0x00000001; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -408,6 +410,9 @@ extern "system" { pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE, lpProfileDir: libc::LPCWSTR, lpcchSize: *mut libc::DWORD) -> libc::BOOL; + pub fn SetHandleInformation(hObject: libc::HANDLE, + dwMask: libc::DWORD, + dwFlags: libc::DWORD) -> libc::BOOL; } // Functions that aren't available on Windows XP, but we still use them and just diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 0b9052672369d..b765bc6e50085 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -82,26 +82,31 @@ impl Socket { SocketAddr::V4(..) => libc::AF_INET, SocketAddr::V6(..) => libc::AF_INET6, }; - let socket = unsafe { - c::WSASocketW(fam, ty, 0, 0 as *mut _, 0, - c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) - }; - match socket { - INVALID_SOCKET => Err(last_error()), - n => Ok(Socket(n)), - } + let socket = try!(unsafe { + match c::WSASocketW(fam, ty, 0, 0 as *mut _, 0, + c::WSA_FLAG_OVERLAPPED) { + INVALID_SOCKET => Err(last_error()), + n => Ok(Socket(n)), + } + }); + try!(socket.set_no_inherit()); + Ok(socket) } pub fn accept(&self, storage: *mut libc::sockaddr, len: *mut libc::socklen_t) -> io::Result { - match unsafe { libc::accept(self.0, storage, len) } { - INVALID_SOCKET => Err(last_error()), - n => Ok(Socket(n)), - } + let socket = try!(unsafe { + match libc::accept(self.0, storage, len) { + INVALID_SOCKET => Err(last_error()), + n => Ok(Socket(n)), + } + }); + try!(socket.set_no_inherit()); + Ok(socket) } pub fn duplicate(&self) -> io::Result { - unsafe { + let socket = try!(unsafe { let mut info: c::WSAPROTOCOL_INFO = mem::zeroed(); try!(cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), @@ -110,12 +115,13 @@ impl Socket { info.iSocketType, info.iProtocol, &mut info, 0, - c::WSA_FLAG_OVERLAPPED | - c::WSA_FLAG_NO_HANDLE_INHERIT) { + c::WSA_FLAG_OVERLAPPED) { INVALID_SOCKET => Err(last_error()), n => Ok(Socket(n)), } - } + }); + try!(socket.set_no_inherit()); + Ok(socket) } pub fn read(&self, buf: &mut [u8]) -> io::Result { @@ -156,6 +162,13 @@ impl Socket { Ok(Some(Duration::new(secs as u64, nsec as u32))) } } + + fn set_no_inherit(&self) -> io::Result<()> { + sys::cvt(unsafe { + c::SetHandleInformation(self.0 as libc::HANDLE, + c::HANDLE_FLAG_INHERIT, 0) + }).map(|_| ()) + } } impl Drop for Socket {