Skip to content

Commit 3fe0ba9

Browse files
committed
libnative: process spawning should not close inherited file descriptors
* The caller should be responsible for cleaning up file descriptors * If a caller safely creates a file descriptor (via native::io::file::open) the returned structure (FileDesc) will try to clean up the file, failing in the process and writing error messages to the screen. * This should not happen as the caller has no public interface for telling the FileDesc structure to NOT free the underlying fd. * Alternatively, if another file is opened under the same fd held by the FileDesc structure returned by native::io::file::open, it will close the wrong file upon destruction.
1 parent 51c7e20 commit 3fe0ba9

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/libnative/io/process.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl Process {
8080
rtio::Ignored => { ret.push(None); Ok(None) }
8181
rtio::InheritFd(fd) => {
8282
ret.push(None);
83-
Ok(Some(file::FileDesc::new(fd, true)))
83+
Ok(Some(file::FileDesc::new(fd, false)))
8484
}
8585
rtio::CreatePipe(readable, _writable) => {
8686
let (reader, writer) = try!(pipe());

src/libstd/io/process.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ pub enum StdioContainer {
378378
Ignored,
379379

380380
/// The specified file descriptor is inherited for the stream which it is
381-
/// specified for.
381+
/// specified for. Ownership of the file descriptor is *not* taken, so the
382+
/// caller must clean it up.
382383
InheritFd(libc::c_int),
383384

384385
/// Creates a pipe for the specified file descriptor which will be created
@@ -605,6 +606,7 @@ impl Drop for Process {
605606

606607
#[cfg(test)]
607608
mod tests {
609+
extern crate native;
608610
use io::process::{Command, Process};
609611
use prelude::*;
610612

@@ -1017,4 +1019,25 @@ mod tests {
10171019
assert!(Process::kill(id, 0).is_ok());
10181020
assert!(Process::kill(id, PleaseExitSignal).is_ok());
10191021
})
1022+
1023+
iotest!(fn dont_close_fd_on_command_spawn() {
1024+
use std::rt::rtio::{Truncate, Write};
1025+
use native::io::file;
1026+
1027+
let path = if cfg!(windows) {
1028+
Path::new("NUL")
1029+
} else {
1030+
Path::new("/dev/null")
1031+
};
1032+
1033+
let mut fdes = match file::open(&path.to_c_str(), Truncate, Write) {
1034+
Ok(f) => f,
1035+
Err(_) => fail!("failed to open file descriptor"),
1036+
};
1037+
1038+
let mut cmd = pwd_cmd();
1039+
let _ = cmd.stdout(InheritFd(fdes.fd()));
1040+
assert!(cmd.status().unwrap().success());
1041+
assert!(fdes.inner_write("extra write\n".as_bytes()).is_ok());
1042+
})
10201043
}

0 commit comments

Comments
 (0)