Skip to content
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

Want way to get BorrowedFd<'static> for 0 1 2 #90809

Closed
ijackson opened this issue Nov 11, 2021 · 8 comments
Closed

Want way to get BorrowedFd<'static> for 0 1 2 #90809

ijackson opened this issue Nov 11, 2021 · 8 comments

Comments

@ijackson
Copy link
Contributor

Logically, stdin stdout and stderr are global static file descriptors. Everyone in the program is entitled to assume they exist (this is logically implied, for example, by the contract of io::stdin()). No-one can own (and therefore drop) them.

IOW there should be a safe way to do

  unsafe { BorrowedFd::borrow_raw_fd::<'static>(0) }

Relates to #87074 (IO safety tracking issue) and I am tripping over it in my #88561 (Command redirection) work.

@the8472
Copy link
Member

the8472 commented Nov 11, 2021

#![feature(io_safety)]
use std::os::unix::io::AsFd;
use std::os::unix::prelude::BorrowedFd;

fn main() {
    let stdout = std::io::stdout();
    let foo: BorrowedFd<'static> = Box::leak(Box::new(stdout)).as_fd();
    dbg!(foo);
}
[src/main.rs:8] foo = BorrowedFd {
    fd: 1,
}

@ijackson
Copy link
Contributor Author

Wow. Thank you. That is inspired. But also a bit bonkers :-). I'm not sure this is the most ergonomic API for this operation...

@ijackson
Copy link
Contributor Author

(Just looked at the definition of io::Stdout and it's not a ZST.)

@sunfishcode
Copy link
Member

Could you say more about what the user of such a function would look like? In what situations does one, as a user of std, need a BorrowedFd<'static>?

@ids1024
Copy link
Contributor

ids1024 commented Jul 8, 2022

Everyone in the program is entitled to assume they exist

It looks like it isn't strictly guaranteed by POSIX that this will always be the case on program start?

If file descriptor 0, 1, or 2 would otherwise be closed after a successful call to one of the exec family of functions, implementations may open an unspecified file for the file descriptor in the new process image. If a standard utility or a conforming application is executed with file descriptor 0 not open for reading or with file descriptor 1 or 2 not open for writing, the environment in which the utility or application is executed shall be deemed non-conforming, and consequently the utility or application might not behave as described in this standard.

Linux seems to do this so file descriptors 0, 1, and 2 will exist after exec. But it's not technically guaranteed.

@the8472
Copy link
Member

the8472 commented Jul 8, 2022

Std tries to ensure that standard file descriptors are open at startup. There are ways those assumptions may be violated, but they involve non-Rust code (in which case we just blame that), unsafe or libraries that ought to be unsafe.

So the current stance is that the standard descriptors can be assumed to be open, anything else is a bug.

@sunfishcode
Copy link
Member

With Rust 1.61.0, std now provides 'static references:

https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html#static-handles-for-locked-stdio

When the io_safety feature is available, you can call as_fd() on these to obtain a BorrowedFd<'static> without any unsafe.

@ijackson Does that meet your needs?

@Dylan-DPC
Copy link
Member

Closing this to clean up the issue tracker. Since there are alternatives possible already as explained above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants