diff options
| author | Martin Nordholts <enselic@gmail.com> | 2022-07-05 19:56:22 +0200 |
|---|---|---|
| committer | Martin Nordholts <enselic@gmail.com> | 2022-08-28 19:46:45 +0200 |
| commit | ddee45e1d7fd34563c13513d974f792fae41a2f7 (patch) | |
| tree | 680a1cbbe412897e2a0acae57e93d6ffe09a07cd /library/std/src | |
| parent | ee285eab69d515114ed54a8e6c25e359acd6b684 (diff) | |
| download | rust-ddee45e1d7fd34563c13513d974f792fae41a2f7.tar.gz rust-ddee45e1d7fd34563c13513d974f792fae41a2f7.zip | |
Support `#[unix_sigpipe = "inherit|sig_dfl|sig_ign"]` on `fn main()`
This makes it possible to instruct libstd to never touch the signal handler for `SIGPIPE`, which makes programs pipeable by default (e.g. with `./your-program | head -n 1`) without `ErrorKind::BrokenPipe` errors.
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/rt.rs | 12 | ||||
| -rw-r--r-- | library/std/src/sys/hermit/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/sgx/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/solid/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/unix/mod.rs | 29 | ||||
| -rw-r--r-- | library/std/src/sys/unsupported/common.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/windows/mod.rs | 2 |
7 files changed, 37 insertions, 14 deletions
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 663537a05fa..7cf3d7d4163 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -73,9 +73,9 @@ macro_rules! rtunwrap { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. #[cfg_attr(test, allow(dead_code))] -unsafe fn init(argc: isize, argv: *const *const u8) { +unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { unsafe { - sys::init(argc, argv); + sys::init(argc, argv, sigpipe); let main_guard = sys::thread::guard::init(); // Next, set up the current Thread with the guard information we just @@ -107,6 +107,7 @@ fn lang_start_internal( main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), argc: isize, argv: *const *const u8, + sigpipe: u8, ) -> Result<isize, !> { use crate::{mem, panic}; let rt_abort = move |e| { @@ -124,7 +125,7 @@ fn lang_start_internal( // prevent libstd from accidentally introducing a panic to these functions. Another is from // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. - panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?; + panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?; let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) .map_err(move |e| { mem::forget(e); @@ -140,11 +141,16 @@ fn lang_start<T: crate::process::Termination + 'static>( main: fn() -> T, argc: isize, argv: *const *const u8, + #[cfg(not(bootstrap))] sigpipe: u8, ) -> isize { let Ok(v) = lang_start_internal( &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(), argc, argv, + #[cfg(bootstrap)] + 2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special + #[cfg(not(bootstrap))] + sigpipe, ); v } diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 60b7a973cc2..61da096ae16 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -98,7 +98,7 @@ pub extern "C" fn __rust_abort() { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(argc: isize, argv: *const *const u8) { +pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { let _ = net::init(); args::init(argc, argv); } diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 696400670e0..b1d32929ecf 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -47,7 +47,7 @@ pub mod locks { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(argc: isize, argv: *const *const u8) { +pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { args::init(argc, argv); } diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs index 778a589d1b7..5867979a2a7 100644 --- a/library/std/src/sys/solid/mod.rs +++ b/library/std/src/sys/solid/mod.rs @@ -56,7 +56,7 @@ pub mod locks { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} +pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {} // SAFETY: must be called only once during runtime cleanup. pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 3a375093099..e11201f60ff 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -44,12 +44,12 @@ pub mod thread_parker; pub mod time; #[cfg(target_os = "espidf")] -pub fn init(argc: isize, argv: *const *const u8) {} +pub fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {} #[cfg(not(target_os = "espidf"))] // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(argc: isize, argv: *const *const u8) { +pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // The standard streams might be closed on application startup. To prevent // std::io::{stdin, stdout,stderr} objects from using other unrelated file // resources opened later, we reopen standards streams when they are closed. @@ -61,8 +61,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { // want! // // Hence, we set SIGPIPE to ignore when the program starts up in order - // to prevent this problem. - reset_sigpipe(); + // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to + // alter this behavior. + reset_sigpipe(sigpipe); stack_overflow::init(); args::init(argc, argv); @@ -151,9 +152,25 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { } } - unsafe fn reset_sigpipe() { + unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] - rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); + { + // We don't want to add this as a public type to libstd, nor do we want to + // duplicate the code, so we choose to include this compiler file like this. + mod sigpipe { + include!("../../../../../compiler/rustc_session/src/config/sigpipe.rs"); + } + + let handler = match sigpipe { + sigpipe::INHERIT => None, + sigpipe::SIG_IGN => Some(libc::SIG_IGN), + sigpipe::SIG_DFL => Some(libc::SIG_DFL), + _ => unreachable!(), + }; + if let Some(handler) = handler { + rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); + } + } } } diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 4c9ade4a8c7..5cd9e57de19 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -6,7 +6,7 @@ pub mod memchr { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} +pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {} // SAFETY: must be called only once during runtime cleanup. // NOTE: this is not guaranteed to run, for example when the program aborts. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index a9846a48488..510f470bfe1 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -48,7 +48,7 @@ cfg_if::cfg_if! { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(_argc: isize, _argv: *const *const u8) { +pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { stack_overflow::init(); // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already |
