You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ui changed from an attribute to a compiler flag: #124480, so the below description is out of date. Someone (maybe me) should update the description.
↑↑↑↑ Important ↑↑↑↑
The feature gate for the issue is #![feature(unix_sigpipe)].
It enables a new fn main() attribute #[unix_sigpipe = "..."].
Usage
Any simple Rust program that writes a sizeable amount of data to stdout will panic if its output is limited via pipes.
fnmain(){loop{println!("hello world");}}
% ./main | head -n 1
hello world
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrac
To prevent panicking we can use the new attribute:
The naming follows the convention used by #![windows_subsystem = "windows|console"] where the values "windows" and "console" have the same names as the actual linker flags: /SUBSYSTEM:WINDOWS and /SUBSYSTEM:CONSOLE.
The names sig_ign and sig_dfl comes from the signal handler names SIG_IGN and SIG_DFL.
Add a test for #[unix_sigpipe = "inherit"] that test that the disposition is actually inherited, rather than assuming SIG_DFL shall always be inherited.
How can we make it easy to put fn lang_start() in an external crate that can be compiled with stable?
We should rename the attribute and attribute values to things that reflect what they do rather than how they do it.
#[unix_sigpipe = "sig_dfl"]
None
#[unix_sigpipe = "sig_ign"]
currently child processes get SIG_IGN, but arguably they should get SIG_DFL since that is what most programs assume, and we explicitly made it that way before.
Should we stabilize sig_dfl or is inherit and sig_ign sufficient? Answer: There are noteworthy examples of real projects that has opted to use SIG_DFL to solve the BrokenPipe problem. Notably rustc itself. So if we don't stabilize sig_dfl, such projects can't make use of our new attribute. Therefore, we also need to stabilize sig_dfl.
Should the attribute go on fn main() or on the top-level module (#![unix_sigpipe="..."])? Answer: It makes a lot of semantic sense to have the attribute on fn main(), because it is a way to configure what the Rust runtime should do before fn main() is invoked. For libraries, no entry point code that modifies SIGPIPE is generated, so allowing the attribute in these situations does not make much sense. See Change process spawning to inherit the parent's signal mask by default #101077 (comment) for small-scale discussion.
Can and should we alter the BrokenPipe error message and make it suggest to use the new attribute? Answer: No, because that would mean we would end up giving developer advice to users that can't act on the advice.
Does this have any impact on defining a stable ABI? Answer: No, because ABI discussion are about enabling things such as calling Rust functions in binary artifacts produced by an older Rust compiler than the current one. That we changed the ABI of fn lang_start() is not relevant. And a stable Rust ABI is not even close (see Define a Rust ABI rfcs#600).
Can we use MSG_NOSIGNAL with send() etc instead of setting SIGPIPE globally? Answer:No, because there is no equivalent for write(), and it would incur an extra syscall for each write-operation, which is likely to have significant performance drawbacks.
Disclaimer: I have taken the liberty to mark some questions resolved that I find unlikely to be controversial. If you would like me to create a proper discussion ticket for any of the resolved or unresolved questions, please let me know!
About tracking issues
Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
View all comments
↓↓↓↓ Important ↓↓↓↓
The ui changed from an attribute to a compiler flag: #124480, so the below description is out of date. Someone (maybe me) should update the description.
↑↑↑↑ Important ↑↑↑↑
The feature gate for the issue is
#![feature(unix_sigpipe)].It enables a new
fn main()attribute#[unix_sigpipe = "..."].Usage
Any simple Rust program that writes a sizeable amount of data to stdout will panic if its output is limited via pipes.
To prevent panicking we can use the new attribute:
% ./main | head -n 1 hello worldMore Info
Please refer to the unstable book section for more details. In short:
#[unix_sigpipe = "..."]sig_ignSIGPIPEhandler toSIG_IGNbefore invokingfn main(). Default behaviour since 2014.sig_dflSIGPIPEhandler toSIG_DFLbefore invokingfn main().inheritSIGPIPEhandler untounched before enteringfn main().The problem with the current
SIGPIPEcode in libstd as well as several other aspects of this problem is discussed extensively at these places:Naming convention
The naming follows the convention used by
#![windows_subsystem = "windows|console"]where the values"windows"and"console"have the same names as the actual linker flags:/SUBSYSTEM:WINDOWSand/SUBSYSTEM:CONSOLE.The names
sig_ignandsig_dflcomes from the signal handler namesSIG_IGNandSIG_DFL.Steps
#[unix_sigpipe = "inherit|sig_dfl"]onfn main()to prevent ignoringSIGPIPE#97802#[unix_sigpipe = "..."]support in rustc miri#2532sigpipe::DEFAULTdistinct)startlang item #106092println!()panic message onErrorKind::BrokenPipe#108980#[unix_sigpipe = "sig_dfl"]unix_sigpipeinstead ofrustc_driver::set_sigpipe_handler#102587unix_sigpipeinstead ofrustc_driver::set_sigpipe_handler#103495#[unix_sigpipe = "sig_ign"]#[unix_sigpipe = "inherit"]rustc_driver::set_sigpipe_handler()rustc_driver::set_sigpipe_handler()#103536#[unix_sigpipe = "inherit"]that test that the disposition is actually inherited, rather than assuming SIG_DFL shall always be inherited.#[unix_sigpipe = "sig_dfl"]onfn main()#120832#[unix_sigpipe = "sig_dfl"]onfn main()#120832Unresolved Questions That Blocks Stabilisation
fn lang_start()in an external crate that can be compiled with stable?#[unix_sigpipe = "sig_dfl"]#[unix_sigpipe = "sig_ign"]SIG_IGN, but arguably they should getSIG_DFLsince that is what most programs assume, and we explicitly made it that way before.exec, see DRAFT: Use a noopSIGPIPEhandler instead ofSIG_IGN#121578 for the trick.#[unix_sigpipe = "inherit"]unchanged?Unresolved Questions That Does Not Block Stabilisation
Because these questions can be resolved incrementally after stabilization.
SIGPIPE, if we want to do it at all?Resolved Questions
-Z unix_sigpipeflag instead, see https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Proposal.3A.20First.20step.20towards.20solving.20the.20SIGPIPE.20problem/near/285499895, at least not initially.sigpipe: u8argument tofn lang_start()on Unix platform viacfg?Answer: No, this is not allowed, see top level comment in https://github.com/rust-lang/rust/blob/master/src/tools/tidy/src/pal.rs
sig_dflor isinheritandsig_ignsufficient?Answer: There are noteworthy examples of real projects that has opted to use
SIG_DFLto solve theBrokenPipeproblem. Notably rustc itself. So if we don't stabilizesig_dfl, such projects can't make use of our new attribute. Therefore, we also need to stabilizesig_dfl.Answer: It makes a lot of semantic sense to have the attribute on fn
main(), because it is a way to configure what the Rust runtime should do beforefn main()is invoked. For libraries, no entry point code that modifiesSIGPIPEis generated, so allowing the attribute in these situations does not make much sense. See Change process spawning to inherit the parent's signal mask by default #101077 (comment) for small-scale discussion.ltoto remove the _signal stub code completely? With aboolit works (see Support#[unix_sigpipe = "inherit|sig_dfl"]onfn main()to prevent ignoringSIGPIPE#97802 (comment)), but with the currentu8we might need to do some tweaks. Answer: There are currently 4 values and I see no feasible way to reduce it to 2.fn lang_start()is not relevant. And a stable Rust ABI is not even close (see Define a Rust ABI rfcs#600).MSG_NOSIGNALwithsend()etc instead of settingSIGPIPEglobally? Answer: No, because there is no equivalent forwrite(), and it would incur an extra syscall for each write-operation, which is likely to have significant performance drawbacks.Disclaimer: I have taken the liberty to mark some questions resolved that I find unlikely to be controversial. If you would like me to create a proper discussion ticket for any of the resolved or unresolved questions, please let me know!
About tracking issues
Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
@rustbot label +T-libs