-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Partial implementation of close
for stdin/out/err (#40032)
#46063
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b645bc9
1188c1a
9f050f9
9d63a4a
8e137e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,11 +11,25 @@ | |
use io; | ||
use libc; | ||
use sys::fd::FileDesc; | ||
use sys::fs::{File, OpenOptions}; | ||
use ffi::CStr; | ||
|
||
pub struct Stdin(()); | ||
pub struct Stdout(()); | ||
pub struct Stderr(()); | ||
|
||
// FIXME: This duplicates code from process_common.rs. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yeah, would it be possible to extract the two to common code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, where should it live? |
||
fn open_null_device (readable: bool) -> io::Result<FileDesc> { | ||
let mut opts = OpenOptions::new(); | ||
opts.read(readable); | ||
opts.write(!readable); | ||
let path = unsafe { | ||
CStr::from_ptr("/dev/null\0".as_ptr() as *const _) | ||
}; | ||
let fd = File::open_c(&path, &opts)?; | ||
Ok(fd.into_fd()) | ||
} | ||
|
||
impl Stdin { | ||
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) } | ||
|
||
|
@@ -25,6 +39,21 @@ impl Stdin { | |
fd.into_raw(); | ||
ret | ||
} | ||
|
||
pub fn close() -> io::Result<()> { | ||
// To close stdin, what we actually do is change its well-known | ||
// file descriptor number to refer to a file open on the null | ||
// device. This protects against code (perhaps in third-party | ||
// libraries) that assumes STDIN_FILENO is always open and always | ||
// refers to the same thing as stdin. | ||
let mut fd = FileDesc::new(libc::STDIN_FILENO); | ||
// If this step succeeds, the "previous" file descriptor returned | ||
// by `fd.replace` is dropped and thus closed. | ||
fd.replace(open_null_device(true)?)?; | ||
// Don't close STDIN_FILENO itself, though! | ||
fd.into_raw(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Errors in those prior There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, good point. Thanks for the tip! |
||
Ok(()) | ||
} | ||
} | ||
|
||
impl Stdout { | ||
|
@@ -40,6 +69,15 @@ impl Stdout { | |
pub fn flush(&self) -> io::Result<()> { | ||
Ok(()) | ||
} | ||
|
||
pub fn close() -> io::Result<()> { | ||
// See commentary for Stdin::close. | ||
|
||
let mut fd = FileDesc::new(libc::STDOUT_FILENO); | ||
fd.replace(open_null_device(false)?)?; | ||
fd.into_raw(); | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl Stderr { | ||
|
@@ -55,6 +93,15 @@ impl Stderr { | |
pub fn flush(&self) -> io::Result<()> { | ||
Ok(()) | ||
} | ||
|
||
pub fn close() -> io::Result<()> { | ||
// See commentary for Stdin::close. | ||
|
||
let mut fd = FileDesc::new(libc::STDERR_FILENO); | ||
fd.replace(open_null_device(false)?)?; | ||
fd.into_raw(); | ||
Ok(()) | ||
} | ||
} | ||
|
||
// FIXME: right now this raw stderr handle is used in a few places because | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the replacement semantics are actually needed when closing, right? That is, I think it's safe for this to return
()
and avoid the first call toduplicate
for the specific use case ofStdout::close
?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I realized the next morning that any caller that actually needs to preserve the old file can just call
duplicate
itself. And that will dovetail better with the semantics ofSetStdHandle
on Windows. I will make this change.