diff options
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/common/args.rs | 16 | ||||
| -rw-r--r-- | src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs | 28 | ||||
| -rw-r--r-- | src/libstd/sys/unix/backtrace/tracing/gcc_s.rs | 36 | ||||
| -rw-r--r-- | src/libstd/sys/unix/ext/fs.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/unix/ext/net.rs | 72 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 35 | ||||
| -rw-r--r-- | src/libstd/sys/unix/os.rs | 52 | ||||
| -rw-r--r-- | src/libstd/sys/unix/time.rs | 318 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext/fs.rs | 19 | ||||
| -rw-r--r-- | src/libstd/sys/windows/process.rs | 27 |
10 files changed, 312 insertions, 295 deletions
diff --git a/src/libstd/sys/common/args.rs b/src/libstd/sys/common/args.rs index 58417540664..e877391fb8b 100644 --- a/src/libstd/sys/common/args.rs +++ b/src/libstd/sys/common/args.rs @@ -48,32 +48,36 @@ mod imp { use mem; use ffi::CStr; - use sync::StaticMutex; + use sys_common::mutex::Mutex; static mut GLOBAL_ARGS_PTR: usize = 0; - static LOCK: StaticMutex = StaticMutex::new(); + static LOCK: Mutex = Mutex::new(); pub unsafe fn init(argc: isize, argv: *const *const u8) { let args = (0..argc).map(|i| { CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec() }).collect(); - let _guard = LOCK.lock(); + LOCK.lock(); let ptr = get_global_ptr(); assert!((*ptr).is_none()); (*ptr) = Some(box args); + LOCK.unlock(); } pub unsafe fn cleanup() { - let _guard = LOCK.lock(); + LOCK.lock(); *get_global_ptr() = None; + LOCK.unlock(); } pub fn clone() -> Option<Vec<Vec<u8>>> { - let _guard = LOCK.lock(); unsafe { + LOCK.lock(); let ptr = get_global_ptr(); - (*ptr).as_ref().map(|s| (**s).clone()) + let ret = (*ptr).as_ref().map(|s| (**s).clone()); + LOCK.unlock(); + return ret } } diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs index de93d3d4e50..ca2e70b5003 100644 --- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs +++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs @@ -18,12 +18,11 @@ /// simple to use it should be used only on iOS devices as the only viable /// option. -use io; use io::prelude::*; +use io; use libc; use mem; -use result::Result::Ok; -use sync::StaticMutex; +use sys::mutex::Mutex; use super::super::printing::print; @@ -37,18 +36,21 @@ pub fn write(w: &mut Write) -> io::Result<()> { // while it doesn't requires lock for work as everything is // local, it still displays much nicer backtraces when a // couple of threads panic simultaneously - static LOCK: StaticMutex = StaticMutex::new(); - let _g = LOCK.lock(); + static LOCK: Mutex = Mutex::new(); + unsafe { + LOCK.lock(); - writeln!(w, "stack backtrace:")?; - // 100 lines should be enough - const SIZE: usize = 100; - let mut buf: [*mut libc::c_void; SIZE] = unsafe { mem::zeroed() }; - let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize}; + writeln!(w, "stack backtrace:")?; + // 100 lines should be enough + const SIZE: usize = 100; + let mut buf: [*mut libc::c_void; SIZE] = mem::zeroed(); + let cnt = backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize; - // skipping the first one as it is write itself - for i in 1..cnt { - print(w, i as isize, buf[i], buf[i])? + // skipping the first one as it is write itself + for i in 1..cnt { + print(w, i as isize, buf[i], buf[i])? + } + LOCK.unlock(); } Ok(()) } diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs index 5f7ad6918cd..c1b45620ab0 100644 --- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs +++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs @@ -12,7 +12,7 @@ use io; use io::prelude::*; use libc; use mem; -use sync::StaticMutex; +use sys_common::mutex::Mutex; use super::super::printing::print; use unwind as uw; @@ -31,24 +31,28 @@ pub fn write(w: &mut Write) -> io::Result<()> { // is semi-reasonable in terms of printing anyway, and we know that all // I/O done here is blocking I/O, not green I/O, so we don't have to // worry about this being a native vs green mutex. - static LOCK: StaticMutex = StaticMutex::new(); - let _g = LOCK.lock(); + static LOCK: Mutex = Mutex::new(); + unsafe { + LOCK.lock(); - writeln!(w, "stack backtrace:")?; + writeln!(w, "stack backtrace:")?; - let mut cx = Context { writer: w, last_error: None, idx: 0 }; - return match unsafe { - uw::_Unwind_Backtrace(trace_fn, - &mut cx as *mut Context as *mut libc::c_void) - } { - uw::_URC_NO_REASON => { - match cx.last_error { - Some(err) => Err(err), - None => Ok(()) + let mut cx = Context { writer: w, last_error: None, idx: 0 }; + let ret = match { + uw::_Unwind_Backtrace(trace_fn, + &mut cx as *mut Context as *mut libc::c_void) + } { + uw::_URC_NO_REASON => { + match cx.last_error { + Some(err) => Err(err), + None => Ok(()) + } } - } - _ => Ok(()), - }; + _ => Ok(()), + }; + LOCK.unlock(); + return ret + } extern fn trace_fn(ctx: *mut uw::_Unwind_Context, arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index a1528458860..bb90a977433 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -88,9 +88,7 @@ pub trait OpenOptionsExt { /// } /// let file = options.open("foo.txt"); /// ``` - #[unstable(feature = "expand_open_options", - reason = "recently added", - issue = "30014")] + #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index a74f7ea13b4..b5287cce484 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -7,7 +7,8 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "unix_socket", reason = "newly added", issue = "32312")] + +#![stable(feature = "unix_socket", since = "1.10.0")] //! Unix-specific networking functionality @@ -75,6 +76,7 @@ enum AddressKind<'a> { /// An address associated with a Unix socket. #[derive(Clone)] +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { addr: libc::sockaddr_un, len: libc::socklen_t, @@ -109,6 +111,7 @@ impl SocketAddr { } /// Returns true iff the address is unnamed. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { true @@ -118,6 +121,7 @@ impl SocketAddr { } /// Returns the contents of this address if it is a `pathname` address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { Some(path) @@ -141,6 +145,7 @@ impl SocketAddr { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.address() { @@ -168,8 +173,6 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::os::unix::net::UnixStream; /// use std::io::prelude::*; /// @@ -179,8 +182,10 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// stream.read_to_string(&mut response).unwrap(); /// println!("{}", response); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); @@ -197,6 +202,7 @@ impl fmt::Debug for UnixStream { impl UnixStream { /// Connects to the socket named by `path`. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> { fn inner(path: &Path) -> io::Result<UnixStream> { unsafe { @@ -213,6 +219,7 @@ impl UnixStream { /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; Ok((UnixStream(i1), UnixStream(i2))) @@ -224,16 +231,19 @@ impl UnixStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propogated to the other /// stream. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result<UnixStream> { self.0.duplicate().map(UnixStream) } /// Returns the socket address of the local half of this connection. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result<SocketAddr> { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Returns the socket address of the remote half of this connection. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result<SocketAddr> { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } @@ -243,6 +253,7 @@ impl UnixStream { /// If the provided value is `None`, then `read` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -252,26 +263,31 @@ impl UnixStream { /// If the provided value is `None`, then `write` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result<Option<Duration>> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result<Option<Duration>> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result<Option<io::Error>> { self.0.take_error() } @@ -281,11 +297,13 @@ impl UnixStream { /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value /// (see the documentation of `Shutdown`). + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { io::Read::read(&mut &*self, buf) @@ -296,6 +314,7 @@ impl io::Read for UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) @@ -306,6 +325,7 @@ impl<'a> io::Read for &'a UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl io::Write for UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { io::Write::write(&mut &*self, buf) @@ -316,6 +336,7 @@ impl io::Write for UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) @@ -326,18 +347,21 @@ impl<'a> io::Write for &'a UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { self.0.into_inner() @@ -349,8 +373,6 @@ impl IntoRawFd for UnixStream { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -377,8 +399,10 @@ impl IntoRawFd for UnixStream { /// // close the listener socket /// drop(listener); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixListener(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); @@ -392,6 +416,7 @@ impl fmt::Debug for UnixListener { impl UnixListener { /// Creates a new `UnixListener` bound to the specified socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> { fn inner(path: &Path) -> io::Result<UnixListener> { unsafe { @@ -412,6 +437,7 @@ impl UnixListener { /// This function will block the calling thread until a new Unix connection /// is established. When established, the corersponding `UnixStream` and /// the remote peer's address will be returned. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; let mut len = mem::size_of_val(&storage) as libc::socklen_t; @@ -425,21 +451,25 @@ impl UnixListener { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result<UnixListener> { self.0.duplicate().map(UnixListener) } /// Returns the local socket address of this listener. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result<SocketAddr> { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result<Option<io::Error>> { self.0.take_error() } @@ -448,29 +478,34 @@ impl UnixListener { /// /// The iterator will never return `None` and will also not yield the /// peer's `SocketAddr` structure. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.0.into_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result<UnixStream>; type IntoIter = Incoming<'a>; @@ -484,10 +519,12 @@ impl<'a> IntoIterator for &'a UnixListener { /// /// It will never return `None`. #[derive(Debug)] +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct Incoming<'a> { listener: &'a UnixListener, } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result<UnixStream>; @@ -505,8 +542,6 @@ impl<'a> Iterator for Incoming<'a> { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap(); @@ -515,8 +550,10 @@ impl<'a> Iterator for Incoming<'a> { /// let (count, address) = socket.recv_from(&mut buf).unwrap(); /// println!("socket {:?} sent {:?}", address, &buf[..count]); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixDatagram(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixDatagram { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixDatagram"); @@ -533,6 +570,7 @@ impl fmt::Debug for UnixDatagram { impl UnixDatagram { /// Creates a Unix datagram socket bound to the given path. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> { fn inner(path: &Path) -> io::Result<UnixDatagram> { unsafe { @@ -548,6 +586,7 @@ impl UnixDatagram { } /// Creates a Unix Datagram socket which is not bound to any address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn unbound() -> io::Result<UnixDatagram> { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; Ok(UnixDatagram(inner)) @@ -556,6 +595,7 @@ impl UnixDatagram { /// Create an unnamed pair of connected sockets. /// /// Returns two `UnixDatagrams`s which are connected to each other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; Ok((UnixDatagram(i1), UnixDatagram(i2))) @@ -565,6 +605,7 @@ impl UnixDatagram { /// /// The `send` method may be used to send data to the specified address. /// `recv` and `recv_from` will only receive data from that address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { unsafe { @@ -583,11 +624,13 @@ impl UnixDatagram { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result<UnixDatagram> { self.0.duplicate().map(UnixDatagram) } /// Returns the address of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result<SocketAddr> { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } @@ -595,6 +638,7 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// /// The `connect` method will connect the socket to a peer. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result<SocketAddr> { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } @@ -603,6 +647,7 @@ impl UnixDatagram { /// /// On success, returns the number of bytes read and the address from /// whence the data came. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; let addr = SocketAddr::new(|addr, len| { @@ -629,6 +674,7 @@ impl UnixDatagram { /// Receives data from the socket. /// /// On success, returns the number of bytes read. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } @@ -636,6 +682,7 @@ impl UnixDatagram { /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> { unsafe { @@ -659,6 +706,7 @@ impl UnixDatagram { /// will return an error if the socket has not already been connected. /// /// On success, returns the number of bytes written. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send(&self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } @@ -668,6 +716,7 @@ impl UnixDatagram { /// If the provided value is `None`, then `recv` and `recv_from` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -677,26 +726,31 @@ impl UnixDatagram { /// If the provided value is `None`, then `send` and `send_to` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result<Option<Duration>> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result<Option<Duration>> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result<Option<io::Error>> { self.0.take_error() } @@ -706,23 +760,27 @@ impl UnixDatagram { /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value /// (see the documentation of `Shutdown`). + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixDatagram { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixDatagram { unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { UnixDatagram(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixDatagram { fn into_raw_fd(self) -> RawFd { self.0.into_inner() diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0969a59ea43..7f23ae53fcd 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -100,31 +100,6 @@ impl FileAttr { } } -#[cfg(any(target_os = "ios", target_os = "macos"))] -// FIXME: update SystemTime to store a timespec and don't lose precision -impl FileAttr { - pub fn modified(&self) -> io::Result<SystemTime> { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_mtime, - tv_usec: (self.stat.st_mtime_nsec / 1000) as libc::suseconds_t, - })) - } - - pub fn accessed(&self) -> io::Result<SystemTime> { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_atime, - tv_usec: (self.stat.st_atime_nsec / 1000) as libc::suseconds_t, - })) - } - - pub fn created(&self) -> io::Result<SystemTime> { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_birthtime, - tv_usec: (self.stat.st_birthtime_nsec / 1000) as libc::suseconds_t, - })) - } -} - #[cfg(target_os = "netbsd")] impl FileAttr { pub fn modified(&self) -> io::Result<SystemTime> { @@ -149,7 +124,7 @@ impl FileAttr { } } -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))] +#[cfg(not(target_os = "netbsd"))] impl FileAttr { pub fn modified(&self) -> io::Result<SystemTime> { Ok(SystemTime::from(libc::timespec { @@ -167,7 +142,9 @@ impl FileAttr { #[cfg(any(target_os = "bitrig", target_os = "freebsd", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "macos", + target_os = "ios"))] pub fn created(&self) -> io::Result<SystemTime> { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_birthtime as libc::time_t, @@ -177,7 +154,9 @@ impl FileAttr { #[cfg(not(any(target_os = "bitrig", target_os = "freebsd", - target_os = "openbsd")))] + target_os = "openbsd", + target_os = "macos", + target_os = "ios")))] pub fn created(&self) -> io::Result<SystemTime> { Err(io::Error::new(io::ErrorKind::Other, "creation time is not available on this platform \ diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 94ebbd70ae8..21ce6b19ceb 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -27,13 +27,13 @@ use path::{self, PathBuf}; use ptr; use slice; use str; -use sync::StaticMutex; +use sys_common::mutex::Mutex; use sys::cvt; use sys::fd; use vec; const TMPBUF_SZ: usize = 128; -static ENV_LOCK: StaticMutex = StaticMutex::new(); +static ENV_LOCK: Mutex = Mutex::new(); /// Returns the platform-specific value of errno #[cfg(not(target_os = "dragonfly"))] @@ -434,10 +434,11 @@ pub unsafe fn environ() -> *mut *const *const c_char { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - let _g = ENV_LOCK.lock(); - return unsafe { + unsafe { + ENV_LOCK.lock(); let mut environ = *environ(); if environ == ptr::null() { + ENV_LOCK.unlock(); panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error()); } @@ -448,8 +449,13 @@ pub fn env() -> Env { } environ = environ.offset(1); } - Env { iter: result.into_iter(), _dont_send_or_sync_me: ptr::null_mut() } - }; + let ret = Env { + iter: result.into_iter(), + _dont_send_or_sync_me: ptr::null_mut(), + }; + ENV_LOCK.unlock(); + return ret + } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { // Strategy (copied from glibc): Variable name and value are separated @@ -471,32 +477,40 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { // environment variables with a nul byte can't be set, so their value is // always None as well let k = CString::new(k.as_bytes())?; - let _g = ENV_LOCK.lock(); - Ok(unsafe { + unsafe { + ENV_LOCK.lock(); let s = libc::getenv(k.as_ptr()) as *const _; - if s.is_null() { + let ret = if s.is_null() { None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) - } - }) + }; + ENV_LOCK.unlock(); + return Ok(ret) + } } pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let k = CString::new(k.as_bytes())?; let v = CString::new(v.as_bytes())?; - let _g = ENV_LOCK.lock(); - cvt(unsafe { - libc::setenv(k.as_ptr(), v.as_ptr(), 1) - }).map(|_| ()) + + unsafe { + ENV_LOCK.lock(); + let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()); + ENV_LOCK.unlock(); + return ret + } } pub fn unsetenv(n: &OsStr) -> io::Result<()> { let nbuf = CString::new(n.as_bytes())?; - let _g = ENV_LOCK.lock(); - cvt(unsafe { - libc::unsetenv(nbuf.as_ptr()) - }).map(|_| ()) + + unsafe { + ENV_LOCK.lock(); + let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ()); + ENV_LOCK.unlock(); + return ret + } } pub fn page_size() -> usize { diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index cc7abe25e35..68eebba9e7b 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -8,37 +8,129 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cmp::Ordering; +use time::Duration; +use libc; + pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; const NSEC_PER_SEC: u64 = 1_000_000_000; +#[derive(Copy, Clone)] +struct Timespec { + t: libc::timespec, +} + +impl Timespec { + fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + if self >= other { + Ok(if self.t.tv_nsec >= other.t.tv_nsec { + Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, + (self.t.tv_nsec - other.t.tv_nsec) as u32) + } else { + Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, + self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - + other.t.tv_nsec as u32) + }) + } else { + match other.sub_timespec(self) { + Ok(d) => Err(d), + Err(d) => Ok(d), + } + } + } + + fn add_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); + let mut secs = secs.expect("overflow when adding duration to time"); + + // Nano calculations can't overflow because nanos are <1B which fit + // in a u32. + let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; + if nsec >= NSEC_PER_SEC as u32 { + nsec -= NSEC_PER_SEC as u32; + secs = secs.checked_add(1).expect("overflow when adding \ + duration to time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as libc::c_long, + }, + } + } + + fn sub_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); + let mut secs = secs.expect("overflow when subtracting duration \ + from time"); + + // Similar to above, nanos can't overflow. + let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; + if nsec < 0 { + nsec += NSEC_PER_SEC as i32; + secs = secs.checked_sub(1).expect("overflow when subtracting \ + duration from time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as libc::c_long, + }, + } + } +} + +impl PartialEq for Timespec { + fn eq(&self, other: &Timespec) -> bool { + self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec + } +} + +impl Eq for Timespec {} + +impl PartialOrd for Timespec { + fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for Timespec { + fn cmp(&self, other: &Timespec) -> Ordering { + let me = (self.t.tv_sec, self.t.tv_nsec); + let other = (other.t.tv_sec, other.t.tv_nsec); + me.cmp(&other) + } +} + #[cfg(any(target_os = "macos", target_os = "ios"))] mod inner { - use cmp::Ordering; use fmt; use libc; - use super::NSEC_PER_SEC; use sync::Once; use sys::cvt; use sys_common::mul_div_u64; use time::Duration; - const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000; + use super::NSEC_PER_SEC; + use super::Timespec; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Instant { t: u64 } - #[derive(Copy, Clone)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct SystemTime { - t: libc::timeval, + t: Timespec, } pub const UNIX_EPOCH: SystemTime = SystemTime { - t: libc::timeval { - tv_sec: 0, - tv_usec: 0, + t: Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }, }, }; @@ -72,113 +164,50 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { - let mut s = SystemTime { - t: libc::timeval { - tv_sec: 0, - tv_usec: 0, - }, + let mut s = libc::timeval { + tv_sec: 0, + tv_usec: 0, }; cvt(unsafe { - libc::gettimeofday(&mut s.t, 0 as *mut _) + libc::gettimeofday(&mut s, 0 as *mut _) }).unwrap(); - return s + return SystemTime::from(s) } pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - if self >= other { - Ok(if self.t.tv_usec >= other.t.tv_usec { - Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, - ((self.t.tv_usec - - other.t.tv_usec) as u32) * 1000) - } else { - Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, - (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) - - other.t.tv_usec as u32) * 1000) - }) - } else { - match other.sub_time(self) { - Ok(d) => Err(d), - Err(d) => Ok(d), - } - } + self.t.sub_timespec(&other.t) } pub fn add_duration(&self, other: &Duration) -> SystemTime { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); - - // Nano calculations can't overflow because nanos are <1B which fit - // in a u32. - let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32; - if usec >= USEC_PER_SEC as u32 { - usec -= USEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); - } - SystemTime { - t: libc::timeval { - tv_sec: secs as libc::time_t, - tv_usec: usec as libc::suseconds_t, - }, - } + SystemTime { t: self.t.add_duration(other) } } pub fn sub_duration(&self, other: &Duration) -> SystemTime { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); - - // Similar to above, nanos can't overflow. - let mut usec = self.t.tv_usec as i32 - - (other.subsec_nanos() / 1000) as i32; - if usec < 0 { - usec += USEC_PER_SEC as i32; - secs = secs.checked_sub(1).expect("overflow when subtracting \ - duration from time"); - } - SystemTime { - t: libc::timeval { - tv_sec: secs as libc::time_t, - tv_usec: usec as libc::suseconds_t, - }, - } + SystemTime { t: self.t.sub_duration(other) } } } impl From<libc::timeval> for SystemTime { fn from(t: libc::timeval) -> SystemTime { - SystemTime { t: t } - } - } - - impl PartialEq for SystemTime { - fn eq(&self, other: &SystemTime) -> bool { - self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec - } - } - - impl Eq for SystemTime {} - - impl PartialOrd for SystemTime { - fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> { - Some(self.cmp(other)) + SystemTime::from(libc::timespec { + tv_sec: t.tv_sec, + tv_nsec: (t.tv_usec * 1000) as libc::c_long, + }) } } - impl Ord for SystemTime { - fn cmp(&self, other: &SystemTime) -> Ordering { - let me = (self.t.tv_sec, self.t.tv_usec); - let other = (other.t.tv_sec, other.t.tv_usec); - me.cmp(&other) + impl From<libc::timespec> for SystemTime { + fn from(t: libc::timespec) -> SystemTime { + SystemTime { t: Timespec { t: t } } } } impl fmt::Debug for SystemTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SystemTime") - .field("tv_sec", &self.t.tv_sec) - .field("tv_usec", &self.t.tv_usec) + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) .finish() } } @@ -209,17 +238,12 @@ mod inner { #[cfg(not(any(target_os = "macos", target_os = "ios")))] mod inner { - use cmp::Ordering; use fmt; use libc; - use super::NSEC_PER_SEC; use sys::cvt; use time::Duration; - #[derive(Copy, Clone)] - struct Timespec { - t: libc::timespec, - } + use super::Timespec; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Instant { @@ -242,7 +266,7 @@ mod inner { impl Instant { pub fn now() -> Instant { - Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) } + Instant { t: now(libc::CLOCK_MONOTONIC) } } pub fn sub_instant(&self, other: &Instant) -> Duration { @@ -271,7 +295,7 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { - SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } + SystemTime { t: now(libc::CLOCK_REALTIME) } } pub fn sub_time(&self, other: &SystemTime) @@ -308,98 +332,16 @@ mod inner { #[cfg(target_os = "dragonfly")] pub type clock_t = libc::c_ulong; - impl Timespec { - pub fn now(clock: clock_t) -> Timespec { - let mut t = Timespec { - t: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - } - }; - cvt(unsafe { - libc::clock_gettime(clock, &mut t.t) - }).unwrap(); - t - } - - fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { - if self >= other { - Ok(if self.t.tv_nsec >= other.t.tv_nsec { - Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, - (self.t.tv_nsec - other.t.tv_nsec) as u32) - } else { - Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, - self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - - other.t.tv_nsec as u32) - }) - } else { - match other.sub_timespec(self) { - Ok(d) => Err(d), - Err(d) => Ok(d), - } - } - } - - fn add_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); - - // Nano calculations can't overflow because nanos are <1B which fit - // in a u32. - let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; - if nsec >= NSEC_PER_SEC as u32 { - nsec -= NSEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); - } - Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, - }, - } - } - - fn sub_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); - - // Similar to above, nanos can't overflow. - let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; - if nsec < 0 { - nsec += NSEC_PER_SEC as i32; - secs = secs.checked_sub(1).expect("overflow when subtracting \ - duration from time"); - } - Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, - }, + fn now(clock: clock_t) -> Timespec { + let mut t = Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, } - } - } - - impl PartialEq for Timespec { - fn eq(&self, other: &Timespec) -> bool { - self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec - } - } - - impl Eq for Timespec {} - - impl PartialOrd for Timespec { - fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> { - Some(self.cmp(other)) - } - } - - impl Ord for Timespec { - fn cmp(&self, other: &Timespec) -> Ordering { - let me = (self.t.tv_sec, self.t.tv_nsec); - let other = (other.t.tv_sec, other.t.tv_nsec); - me.cmp(&other) - } + }; + cvt(unsafe { + libc::clock_gettime(clock, &mut t.t) + }).unwrap(); + t } } diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index d378a6853f3..4388a0bdff2 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -19,9 +19,7 @@ use sys; use sys_common::{AsInnerMut, AsInner}; /// Windows-specific extensions to `OpenOptions` -#[unstable(feature = "open_options_ext", - reason = "may require more thought/methods", - issue = "27720")] +#[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile` /// with the specified value. @@ -34,7 +32,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// #![feature(open_options_ext)] /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; /// @@ -42,6 +39,7 @@ pub trait OpenOptionsExt { /// // to call `stat()` on the file /// let file = OpenOptions::new().access_mode(0).open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn access_mode(&mut self, access: u32) -> &mut Self; /// Overrides the `dwShareMode` argument to the call to `CreateFile` with @@ -55,7 +53,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// #![feature(open_options_ext)] /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; /// @@ -65,6 +62,7 @@ pub trait OpenOptionsExt { /// .share_mode(0) /// .open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn share_mode(&mut self, val: u32) -> &mut Self; /// Sets extra flags for the `dwFileFlags` argument to the call to @@ -88,9 +86,7 @@ pub trait OpenOptionsExt { /// } /// let file = options.open("foo.txt"); /// ``` - #[unstable(feature = "expand_open_options", - reason = "recently added", - issue = "30014")] + #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: u32) -> &mut Self; /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to @@ -111,7 +107,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```rust,ignore - /// #![feature(open_options_ext)] /// extern crate winapi; /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; @@ -120,17 +115,17 @@ pub trait OpenOptionsExt { /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN) /// .open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn attributes(&mut self, val: u32) -> &mut Self; /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to /// the specified value (or combines it with `custom_flags` and `attributes` /// to set the `dwFlagsAndAttributes` for `CreateFile`). + #[stable(feature = "open_options_ext", since = "1.10.0")] fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions; } -#[unstable(feature = "open_options_ext", - reason = "may require more thought/methods", - issue = "27720")] +#[stable(feature = "open_options_ext", since = "1.10.0")] impl OpenOptionsExt for OpenOptions { fn access_mode(&mut self, access: u32) -> &mut OpenOptions { self.as_inner_mut().access_mode(access); self diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index a0ad866c69d..3ca75cf3643 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -24,7 +24,7 @@ use mem; use os::windows::ffi::OsStrExt; use path::Path; use ptr; -use sync::StaticMutex; +use sys::mutex::Mutex; use sys::c; use sys::fs::{OpenOptions, File}; use sys::handle::Handle; @@ -75,6 +75,10 @@ pub struct StdioPipes { pub stderr: Option<AnonPipe>, } +struct DropGuard<'a> { + lock: &'a Mutex, +} + impl Command { pub fn new(program: &OsStr) -> Command { Command { @@ -173,8 +177,8 @@ impl Command { // // For more information, msdn also has an article about this race: // http://support.microsoft.com/kb/315939 - static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); - let _lock = CREATE_PROCESS_LOCK.lock(); + static CREATE_PROCESS_LOCK: Mutex = Mutex::new(); + let _guard = DropGuard::new(&CREATE_PROCESS_LOCK); let mut pipes = StdioPipes { stdin: None, @@ -224,6 +228,23 @@ impl fmt::Debug for Command { } } +impl<'a> DropGuard<'a> { + fn new(lock: &'a Mutex) -> DropGuard<'a> { + unsafe { + lock.lock(); + DropGuard { lock: lock } + } + } +} + +impl<'a> Drop for DropGuard<'a> { + fn drop(&mut self) { + unsafe { + self.lock.unlock(); + } + } +} + impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> { |
