about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-05-29 19:24:40 +0000
committerbors <bors@rust-lang.org>2015-05-29 19:24:40 +0000
commit996fb8d001e52e9c8b558515f3706d39f4b6b700 (patch)
tree6427a548914b23cc143112e2cb007fb4d98f010f /src/libstd/sys/windows
parent84254948c2e7eee3869e132453d7b870639890f3 (diff)
parent3dd3450484c1a914d07da2ab522e3bd27ce2a4bb (diff)
downloadrust-996fb8d001e52e9c8b558515f3706d39f4b6b700.tar.gz
rust-996fb8d001e52e9c8b558515f3706d39f4b6b700.zip
Auto merge of #25494 - alexcrichton:stdio-from-raw, r=aturon
This commit implements a number of standard traits for the standard library's
process I/O handles. The `FromRaw{Fd,Handle}` traits are now implemented for the
`Stdio` type and the `AsRaw{Fd,Handle}` traits are now implemented for the
`Child{Stdout,Stdin,Stderr}` types.

The stability markers for these implementations mention that they are stable for
1.1 as I will nominate this commit for cherry-picking to beta.
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/ext/mod.rs1
-rw-r--r--src/libstd/sys/windows/ext/process.rs69
-rw-r--r--src/libstd/sys/windows/handle.rs49
-rw-r--r--src/libstd/sys/windows/process.rs17
4 files changed, 122 insertions, 14 deletions
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
index 08dfa4cc877..ead533e7759 100644
--- a/src/libstd/sys/windows/ext/mod.rs
+++ b/src/libstd/sys/windows/ext/mod.rs
@@ -20,6 +20,7 @@ pub mod ffi;
 pub mod fs;
 pub mod io;
 pub mod raw;
+pub mod process;
 
 /// A prelude for conveniently writing platform-specific code.
 ///
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
new file mode 100644
index 00000000000..0fd43a450f3
--- /dev/null
+++ b/src/libstd/sys/windows/ext/process.rs
@@ -0,0 +1,69 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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.
+
+//! Extensions to `std::process` for Windows.
+
+#![stable(feature = "from_raw_os", since = "1.1.0")]
+
+use os::windows::io::{FromRawHandle, RawHandle, AsRawHandle};
+use process;
+use sys;
+use sys_common::{AsInner, FromInner};
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawHandle for process::Stdio {
+    /// Creates a new instance of `Stdio` from the raw underlying handle.
+    ///
+    /// When this `Stdio` is used as an I/O handle for a child process the given
+    /// handle will be duplicated via `DuplicateHandle` to ensure that the
+    /// handle has the correct permissions to cross the process boundary.
+    ///
+    /// Note that this function **does not** take ownership of the handle
+    /// provided and it will **not** be closed when `Stdio` goes out of scope.
+    /// As a result this method is unsafe because due to the lack of knowledge
+    /// about the lifetime of the provided handle, this could cause another I/O
+    /// primitive's ownership property of its handle to be violated.
+    ///
+    /// Also note that this handle may be used multiple times to spawn
+    /// processes. For example the `Command::spawn` function could be called
+    /// more than once to spawn more than one process sharing this handle.
+    unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
+        let handle = sys::handle::RawHandle::new(handle as *mut _);
+        process::Stdio::from_inner(sys::process::Stdio::Handle(handle))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl AsRawHandle for process::Child {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl AsRawHandle for process::ChildStdin {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl AsRawHandle for process::ChildStdout {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl AsRawHandle for process::ChildStderr {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index c835d503388..a566c5eff32 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -15,26 +15,55 @@ use io;
 use libc::funcs::extra::kernel32::{GetCurrentProcess, DuplicateHandle};
 use libc::{self, HANDLE};
 use mem;
+use ops::Deref;
 use ptr;
 use sys::cvt;
 
-pub struct Handle(HANDLE);
+/// An owned container for `HANDLE` object, closing them on Drop.
+///
+/// All methods are inherited through a `Deref` impl to `RawHandle`
+pub struct Handle(RawHandle);
 
-unsafe impl Send for Handle {}
-unsafe impl Sync for Handle {}
+/// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
+/// as well as Rust-y methods.
+///
+/// This does **not** drop the handle when it goes out of scope, use `Handle`
+/// instead for that.
+#[derive(Copy, Clone)]
+pub struct RawHandle(HANDLE);
+
+unsafe impl Send for RawHandle {}
+unsafe impl Sync for RawHandle {}
 
 impl Handle {
     pub fn new(handle: HANDLE) -> Handle {
-        Handle(handle)
+        Handle(RawHandle::new(handle))
     }
 
-    pub fn raw(&self) -> HANDLE { self.0 }
-
     pub fn into_raw(self) -> HANDLE {
-        let ret = self.0;
+        let ret = self.raw();
         mem::forget(self);
         return ret;
     }
+}
+
+impl Deref for Handle {
+    type Target = RawHandle;
+    fn deref(&self) -> &RawHandle { &self.0 }
+}
+
+impl Drop for Handle {
+    fn drop(&mut self) {
+        unsafe { let _ = libc::CloseHandle(self.raw()); }
+    }
+}
+
+impl RawHandle {
+    pub fn new(handle: HANDLE) -> RawHandle {
+        RawHandle(handle)
+    }
+
+    pub fn raw(&self) -> HANDLE { self.0 }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
@@ -79,9 +108,3 @@ impl Handle {
         Ok(Handle::new(ret))
     }
 }
-
-impl Drop for Handle {
-    fn drop(&mut self) {
-        unsafe { let _ = libc::CloseHandle(self.0); }
-    }
-}
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 178b6ea42d2..05073e60f5d 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -27,7 +27,7 @@ use ptr;
 use sync::StaticMutex;
 use sys::c;
 use sys::fs::{OpenOptions, File};
-use sys::handle::Handle;
+use sys::handle::{Handle, RawHandle};
 use sys::pipe::AnonPipe;
 use sys::stdio;
 use sys::{self, cvt};
@@ -109,6 +109,7 @@ pub enum Stdio {
     Inherit,
     Piped(AnonPipe),
     None,
+    Handle(RawHandle),
 }
 
 impl Process {
@@ -217,6 +218,8 @@ impl Process {
             }
         }
     }
+
+    pub fn handle(&self) -> &Handle { &self.handle }
 }
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -353,6 +356,15 @@ fn make_dirp(d: Option<&OsString>) -> (*const u16, Vec<u16>) {
 }
 
 impl Stdio {
+    pub fn clone_if_copy(&self) -> Stdio {
+        match *self {
+            Stdio::Inherit => Stdio::Inherit,
+            Stdio::None => Stdio::None,
+            Stdio::Handle(handle) => Stdio::Handle(handle),
+            Stdio::Piped(_) => unreachable!(),
+        }
+    }
+
     fn to_handle(&self, stdio_id: libc::DWORD) -> io::Result<Handle> {
         use libc::DUPLICATE_SAME_ACCESS;
 
@@ -362,6 +374,9 @@ impl Stdio {
                     io.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
                 })
             }
+            Stdio::Handle(ref handle) => {
+                handle.duplicate(0, true, DUPLICATE_SAME_ACCESS)
+            }
             Stdio::Piped(ref pipe) => {
                 pipe.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
             }