diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 434b978ae31..7ba58406ef1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,5 +1,3 @@ -#![feature(unix_sigpipe)] - // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see @@ -34,7 +32,6 @@ // https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef // for an example of how to do so. -#[unix_sigpipe = "sig_dfl"] fn main() { // See the comment at the top of this file for an explanation of this. #[cfg(feature = "jemalloc-sys")] diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9d3aac66c41..9c33cc8ed0b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -396,10 +396,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - gated!( - unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, - EncodeCrossCrate::Yes, experimental!(unix_sigpipe) - ), ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e7d7a9f380b..fe50499db76 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -619,8 +619,6 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), - /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE. - (unstable, unix_sigpipe, "1.65.0", Some(97889)), /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsized fn parameters. diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index db150cc1f87..36f9dda7250 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -20,7 +20,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, }; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; @@ -809,6 +809,7 @@ fn test_unstable_options_tracking_hash() { tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); tracked!(no_unique_section_names, true); + tracked!(on_broken_pipe, OnBrokenPipe::Kill); tracked!(oom, OomStrategy::Panic); tracked!(osx_rpath_install_name, true); tracked!(packed_bundled_libs, true); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index a545c170297..8878310d6e9 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -695,9 +695,6 @@ passes_transparent_incompatible = passes_undefined_naked_function_abi = Rust ABI is unsupported in naked functions -passes_unix_sigpipe_values = - valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` - passes_unknown_external_lang_item = unknown external lang item: `{$lang_item}` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c403e9196fa..e60aa27dba2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2523,7 +2523,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::automatically_derived, sym::start, sym::rustc_main, - sym::unix_sigpipe, sym::derive, sym::test, sym::test_case, diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 438c583db49..d52092f2aa9 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -12,8 +12,7 @@ use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use crate::errors::{ - AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain, - MultipleStartFunctions, NoMainErr, UnixSigpipeValues, + AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr, }; struct EntryContext<'tcx> { @@ -67,11 +66,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), ); match entry_point_type { - EntryPointType::None => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } - } + EntryPointType::None => (), _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { for attr in [sym::start, sym::rustc_main] { if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { @@ -81,9 +76,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } EntryPointType::MainNamed => (), EntryPointType::OtherMain => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe }); - } ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { @@ -98,9 +90,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } } EntryPointType::Start => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } if ctxt.start_fn.is_none() { ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { @@ -120,7 +109,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, Some((def_id.to_def_id(), EntryFnType::Start)) } else if let Some((local_def_id, _)) = visitor.attr_main_fn { let def_id = local_def_id.to_def_id(); - Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })) + Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() @@ -133,31 +122,19 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, return None; } - return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })); + return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })); } no_main_err(tcx, visitor); None } } -fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { - if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) { - match (attr.value_str(), attr.meta_item_list()) { - (Some(sym::inherit), None) => sigpipe::INHERIT, - (Some(sym::sig_ign), None) => sigpipe::SIG_IGN, - (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL, - (Some(_), None) => { - tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span }); - sigpipe::DEFAULT - } - _ => { - // Keep going so that `fn emit_malformed_attribute()` can print - // an excellent error message - sigpipe::DEFAULT - } - } - } else { - sigpipe::DEFAULT +fn sigpipe(tcx: TyCtxt<'_>) -> u8 { + match tcx.sess.opts.unstable_opts.on_broken_pipe { + rustc_target::spec::OnBrokenPipe::Default => sigpipe::DEFAULT, + rustc_target::spec::OnBrokenPipe::Kill => sigpipe::SIG_DFL, + rustc_target::spec::OnBrokenPipe::Error => sigpipe::SIG_IGN, + rustc_target::spec::OnBrokenPipe::Inherit => sigpipe::INHERIT, } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 03a607348e8..743faf54560 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1259,13 +1259,6 @@ pub struct ExternMain { pub span: Span, } -#[derive(Diagnostic)] -#[diag(passes_unix_sigpipe_values)] -pub struct UnixSigpipeValues { - #[primary_span] - pub span: Span, -} - pub struct NoMainErr { pub sp: Span, pub crate_name: Symbol, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ad66e5e1c2b..f2bdabbf394 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2909,7 +2909,9 @@ pub(crate) mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; - use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi}; + use rustc_target::spec::{ + CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, + }; use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -2973,6 +2975,7 @@ pub(crate) mod dep_tracking { InstrumentXRay, CrateType, MergeFunctions, + OnBrokenPipe, PanicStrategy, RelroLevel, OptLevel, diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs index 1fadc75cfd0..1830ee03485 100644 --- a/compiler/rustc_session/src/config/sigpipe.rs +++ b/compiler/rustc_session/src/config/sigpipe.rs @@ -1,6 +1,6 @@ //! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`! -/// The default value if `#[unix_sigpipe]` is not specified. This resolves +/// The default value if `-Zon-broken-pipe=...` is not specified. This resolves /// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`. /// /// Note that `SIG_IGN` has been the Rust default since 2014. See diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7355e5b6953..65660286dd7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -12,7 +12,7 @@ use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi, }; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -378,6 +378,7 @@ mod desc { pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; + pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_oom_strategy: &str = "either `panic` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; @@ -708,6 +709,17 @@ mod parse { true } + pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool { + match v { + // OnBrokenPipe::Default can't be explicitly specified + Some("kill") => *slot = OnBrokenPipe::Kill, + Some("error") => *slot = OnBrokenPipe::Error, + Some("inherit") => *slot = OnBrokenPipe::Inherit, + _ => return false, + } + true + } + pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool { match v { Some("panic") => *slot = OomStrategy::Panic, @@ -1833,6 +1845,8 @@ options! { "do not use unique names for text and data sections when -Z function-sections is used"), normalize_docs: bool = (false, parse_bool, [TRACKED], "normalize associated items in rustdoc when generating documentation"), + on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED], + "behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"), oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED], "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7fe94c2e82b..9c556f1152a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1936,7 +1936,6 @@ symbols! { unit, universal_impl_trait, unix, - unix_sigpipe, unlikely, unmarked_api, unnamed_fields, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index bd347c1b4b3..cbb248a0fc2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -778,6 +778,14 @@ pub enum PanicStrategy { Abort, } +#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)] +pub enum OnBrokenPipe { + Default, + Kill, + Error, + Inherit, +} + impl PanicStrategy { pub fn desc(&self) -> &str { match *self { diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 59e118f81ab..46f691d7b75 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -74,7 +74,7 @@ macro_rules! rtunwrap { // // Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to // `SIG_IGN`. Applications have good reasons to want a different behavior -// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that +// though, so there is a `-Zon-broken-pipe` compiler flag that // can be used to select how `SIGPIPE` shall be setup (if changed at all) before // `fn main()` is called. See // for more info. diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 01d7fb31d7d..1ac5729c02f 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -55,8 +55,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // want! // // Hence, we set SIGPIPE to ignore when the program starts up in order - // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to - // alter this behavior. + // to prevent this problem. Use `-Zon-broken-pipe=...` to alter this + // behavior. reset_sigpipe(sigpipe); stack_overflow::init(); @@ -190,7 +190,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { _ => unreachable!(), }; if sigpipe_attr_specified { - UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed); + ON_BROKEN_PIPE_FLAG_USED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); @@ -210,7 +210,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "fuchsia", target_os = "horizon", )))] -static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = +static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool = crate::sync::atomic::AtomicBool::new(false); #[cfg(not(any( @@ -219,8 +219,8 @@ static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = target_os = "fuchsia", target_os = "horizon", )))] -pub(crate) fn unix_sigpipe_attr_specified() -> bool { - UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed) +pub(crate) fn on_broken_pipe_flag_used() -> bool { + ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed) } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index f2947161cd5..e2fca8c7e63 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -353,11 +353,11 @@ impl Command { // Inherit the signal mask from the parent rather than resetting it (i.e. do not call // pthread_sigmask). - // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL. - // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility. + // If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL. + // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // - // #[unix_sigpipe] is an opportunity to change the default here. - if !crate::sys::pal::unix_sigpipe_attr_specified() { + // -Zon-broken-pipe is an opportunity to change the default here. + if !crate::sys::pal::on_broken_pipe_flag_used() { #[cfg(target_os = "android")] // see issue #88585 { let mut action: libc::sigaction = mem::zeroed(); @@ -450,7 +450,7 @@ impl Command { ) -> io::Result> { use crate::mem::MaybeUninit; use crate::sys::weak::weak; - use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified}; + use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; if self.get_gid().is_some() || self.get_uid().is_some() @@ -612,11 +612,11 @@ impl Command { // Inherit the signal mask from this process rather than resetting it (i.e. do not call // posix_spawnattr_setsigmask). - // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL. - // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility. + // If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL. + // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // - // #[unix_sigpipe] is an opportunity to change the default here. - if !unix_sigpipe_attr_specified() { + // -Zon-broken-pipe is an opportunity to change the default here. + if !on_broken_pipe_flag_used() { let mut default_set = MaybeUninit::::uninit(); cvt(sigemptyset(default_set.as_mut_ptr()))?; cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1d46a158f9e..48a6602e2df 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1006,6 +1006,13 @@ pub fn rustc_cargo( cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); + // If the rustc output is piped to e.g. `head -n1` we want the process to be + // killed, rather than having an error bubble up and cause a panic. + // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it. + if compiler.stage != 0 { + cargo.rustflag("-Zon-broken-pipe=kill"); + } + // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary // and may just be a time sink. if compiler.stage != 0 { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 2e2c5e9e6f8..21344a4224e 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -471,7 +471,7 @@ impl Step for Rustdoc { features.push("jemalloc".to_string()); } - let cargo = prepare_tool_cargo( + let mut cargo = prepare_tool_cargo( builder, build_compiler, Mode::ToolRustc, @@ -482,6 +482,14 @@ impl Step for Rustdoc { features.as_slice(), ); + // If the rustdoc output is piped to e.g. `head -n1` we want the process + // to be killed, rather than having an error bubble up and cause a + // panic. + // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it. + if build_compiler.stage > 0 { + cargo.rustflag("-Zon-broken-pipe=kill"); + } + let _guard = builder.msg_tool( Kind::Build, Mode::ToolRustc, diff --git a/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md b/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md new file mode 100644 index 00000000000..bdc175f3b0a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md @@ -0,0 +1,84 @@ +# `on-broken-pipe` + +-------------------- + +The tracking issue for this feature is: [#97889] + +Note: The ui for this feature was previously an attribute named `#[unix_sigpipe = "..."]`. + +[#97889]: https://github.com/rust-lang/rust/issues/97889 + +--- + + +## Overview + +The `-Zon-broken-pipe=...` compiler flag can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This flag is ignored on non-Unix targets. The flag can be used with three different values or be omitted entirely. It affects `SIGPIPE` before `fn main()` and before children get `exec()`'ed: + +| Compiler flag | `SIGPIPE` before `fn main()` | `SIGPIPE` before child `exec()` | +|----------------------------|------------------------------|---------------------------------| +| not used | `SIG_IGN` | `SIG_DFL` | +| `-Zon-broken-pipe=kill` | `SIG_DFL` | not touched | +| `-Zon-broken-pipe=error` | `SIG_IGN` | not touched | +| `-Zon-broken-pipe=inherit` | not touched | not touched | + + +## `-Zon-broken-pipe` not used + +If `-Zon-broken-pipe` is not used, libstd will behave in the manner it has since 2014, before Rust 1.0. `SIGPIPE` will be set to `SIG_IGN` before `fn main()` and result in `EPIPE` errors which are converted to `std::io::ErrorKind::BrokenPipe`. + +When spawning child processes, `SIGPIPE` will be set to `SIG_DFL` before doing the underlying `exec()` syscall. + + +## `-Zon-broken-pipe=kill` + +Set the `SIGPIPE` handler to `SIG_DFL` before invoking `fn main()`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`. + +### Example + +```rust,no_run +fn main() { + loop { + println!("hello world"); + } +} +``` + +```console +$ rustc -Zon-broken-pipe=kill main.rs +$ ./main | head -n1 +hello world +``` + +## `-Zon-broken-pipe=error` + +Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_IGN` for `SIGPIPE`. + +### Example + +```rust,no_run +fn main() { + loop { + println!("hello world"); + } +} +``` + +```console +$ rustc -Zon-broken-pipe=error main.rs +$ ./main | head -n1 +hello world +thread 'main' panicked at library/std/src/io/stdio.rs:1118:9: +failed printing to stdout: Broken pipe (os error 32) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +## `-Zon-broken-pipe=inherit` + +Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `-Zon-broken-pipe=kill`. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`. diff --git a/src/doc/unstable-book/src/language-features/unix-sigpipe.md b/src/doc/unstable-book/src/language-features/unix-sigpipe.md deleted file mode 100644 index 7ed6a7de895..00000000000 --- a/src/doc/unstable-book/src/language-features/unix-sigpipe.md +++ /dev/null @@ -1,62 +0,0 @@ -# `unix_sigpipe` - -The tracking issue for this feature is: [#97889] - -[#97889]: https://github.com/rust-lang/rust/issues/97889 - ---- - -The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants: -* `#[unix_sigpipe = "inherit"]` -* `#[unix_sigpipe = "sig_dfl"]` -* `#[unix_sigpipe = "sig_ign"]` - -## `#[unix_sigpipe = "inherit"]` - -Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`. - -## `#[unix_sigpipe = "sig_dfl"]` - -Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. - -### Example - -```rust,no_run -#![feature(unix_sigpipe)] -#[unix_sigpipe = "sig_dfl"] -fn main() { loop { println!("hello world"); } } -``` - -```bash -% ./main | head -n 1 -hello world -``` - -## `#[unix_sigpipe = "sig_ign"]` - -Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. - -This is what libstd has done by default since 2014. (However, see the note on child processes below.) - -### Example - -```rust,no_run -#![feature(unix_sigpipe)] -#[unix_sigpipe = "sig_ign"] -fn main() { loop { println!("hello world"); } } -``` - -```bash -% ./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 backtrace -``` - -### Note on child processes - -When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to -reset `SIGPIPE` to `SIG_DFL`. - -If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of -`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior. diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 2242768a568..97c5e9a0eac 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -387,7 +387,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( let main_ptr = ecx.fn_ptr(FnVal::Instance(entry_instance)); // Always using DEFAULT is okay since we don't support signals in Miri anyway. - // (This means we are effectively ignoring `#[unix_sigpipe]`.) + // (This means we are effectively ignoring `-Zon-broken-pipe`.) let sigpipe = rustc_session::config::sigpipe::DEFAULT; ecx.call_function( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs index 55b9a1dfdcb..1fba2e2e4d3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs @@ -207,7 +207,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)), ungated!(start, Normal, template!(Word), WarnFollowing), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs index b81f46d1211..5b499a1fa1f 100644 --- a/src/tools/rustdoc/main.rs +++ b/src/tools/rustdoc/main.rs @@ -1,6 +1,3 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] fn main() { rustdoc::main() } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs deleted file mode 100644 index 5d95fc70e78..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr deleted file mode 100644 index c1b4470d54a..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-bare.rs:3:1 - | -LL | #[unix_sigpipe] - | ^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs deleted file mode 100644 index f5fa177f29c..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] -#![unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute cannot be used at crate level - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr deleted file mode 100644 index fdfa3018086..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: `unix_sigpipe` attribute cannot be used at crate level - --> $DIR/unix_sigpipe-crate.rs:2:1 - | -LL | #![unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn main() {} - | ---- the inner attribute doesn't annotate this function - | -help: perhaps you meant to use an outer attribute - | -LL - #![unix_sigpipe = "sig_dfl"] -LL + #[unix_sigpipe = "sig_dfl"] - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs deleted file mode 100644 index 294cb38526b..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_ign"] -#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr deleted file mode 100644 index c2a3b9f45f9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: multiple `unix_sigpipe` attributes - --> $DIR/unix_sigpipe-different-duplicates.rs:4:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unix_sigpipe-different-duplicates.rs:3:1 - | -LL | #[unix_sigpipe = "sig_ign"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs deleted file mode 100644 index eccb23021b6..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] -#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr deleted file mode 100644 index c86e54a1e53..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: multiple `unix_sigpipe` attributes - --> $DIR/unix_sigpipe-duplicates.rs:4:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unix_sigpipe-duplicates.rs:3:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs deleted file mode 100644 index 462ae24a884..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe(sig_dfl)] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr deleted file mode 100644 index a020f21e6ca..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-ident-list.rs:3:1 - | -LL | #[unix_sigpipe(sig_dfl)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs deleted file mode 100644 index 16731a4ba2c..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -fn f() {} - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr deleted file mode 100644 index fcdd5db8f29..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-non-main-fn.rs:3:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs deleted file mode 100644 index a2435258620..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(unix_sigpipe)] - -mod m { - #[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()` - fn main() {} -} - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr deleted file mode 100644 index 98afb62fdb4..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on root `fn main()` - --> $DIR/unix_sigpipe-non-root-main.rs:4:5 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs deleted file mode 100644 index 945b820f9e0..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(start)] -#![feature(unix_sigpipe)] - -#[start] -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr deleted file mode 100644 index 3d56b3655c9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-start.rs:5:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs deleted file mode 100644 index 22326835623..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr deleted file mode 100644 index b62c086e360..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-str-list.rs:3:1 - | -LL | #[unix_sigpipe("sig_dfl")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs deleted file mode 100644 index 662779c0821..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -struct S; - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr deleted file mode 100644 index a8fc51bdbc4..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-struct.rs:3:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs deleted file mode 100644 index 4ec25de00ec..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr deleted file mode 100644 index d750443e4a9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` - --> $DIR/unix_sigpipe-wrong.rs:3:1 - | -LL | #[unix_sigpipe = "wrong"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs b/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs deleted file mode 100644 index 46dc3f6cc17..00000000000 --- a/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![crate_type = "bin"] - -#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature -fn main () {} diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr deleted file mode 100644 index 88c18e72683..00000000000 --- a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature - --> $DIR/feature-gate-unix_sigpipe.rs:3:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #97889 for more information - = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs index 1df8c765cbd..798db3c0f8c 100644 --- a/tests/ui/process/println-with-broken-pipe.rs +++ b/tests/ui/process/println-with-broken-pipe.rs @@ -6,16 +6,14 @@ //@ ignore-horizon //@ ignore-android //@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" +//@ compile-flags: -Zon-broken-pipe=error // Test what the error message looks like when `println!()` panics because of // `std::io::ErrorKind::BrokenPipe` -#![feature(unix_sigpipe)] - use std::env; use std::process::{Command, Stdio}; -#[unix_sigpipe = "sig_ign"] fn main() { let mut args = env::args(); let me = args.next().unwrap(); diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_dfl.rs similarity index 72% rename from tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs rename to tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_dfl.rs index 7f95fa7ebbe..b179e484524 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_dfl.rs @@ -1,8 +1,6 @@ //@ aux-crate: sigpipe_utils=sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=inherit -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] fn main() { sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_ign.rs similarity index 72% rename from tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs rename to tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_ign.rs index d96e8b8ef84..5ea435521ec 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_ign.rs @@ -1,8 +1,6 @@ //@ aux-crate: sigpipe_utils=sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=inherit -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] fn main() { sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-sigpipe-disposition.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs similarity index 100% rename from tests/ui/attributes/unix_sigpipe/auxiliary/assert-sigpipe-disposition.rs rename to tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs similarity index 100% rename from tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs rename to tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-and-child-processes.rs b/tests/ui/runtime/on-broken-pipe/child-processes.rs similarity index 55% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-and-child-processes.rs rename to tests/ui/runtime/on-broken-pipe/child-processes.rs index 9d1bd9f9607..0da2347481b 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-and-child-processes.rs +++ b/tests/ui/runtime/on-broken-pipe/child-processes.rs @@ -1,25 +1,20 @@ -//@ revisions: default sig_dfl sig_ign inherit +//@ revisions: default error kill inherit //@ ignore-cross-compile because aux-bin does not yet support it //@ only-unix because SIGPIPE is a unix thing //@ run-pass //@ aux-bin:assert-sigpipe-disposition.rs //@ aux-crate:sigpipe_utils=sigpipe-utils.rs +//@ [kill] compile-flags: -Zunstable-options -Zon-broken-pipe=kill +//@ [error] compile-flags: -Zunstable-options -Zon-broken-pipe=error +//@ [inherit] compile-flags: -Zunstable-options -Zon-broken-pipe=inherit // Checks the signal disposition of `SIGPIPE` in child processes, and in our own -// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is -// the default. But there is a difference in how `SIGPIPE` is treated in child -// processes with and without the attribute. Search for -// `unix_sigpipe_attr_specified()` in the code base to learn more. - -#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))] +// process for robustness. extern crate sigpipe_utils; use sigpipe_utils::*; -#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")] -#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")] -#[cfg_attr(inherit, unix_sigpipe = "inherit")] fn main() { // By default we get SIG_IGN but the child gets SIG_DFL through an explicit // reset before exec: @@ -27,18 +22,18 @@ fn main() { #[cfg(default)] let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_DFL"); - // With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too - // without any special code running before exec. - #[cfg(sig_dfl)] + // We get SIG_DFL and the child does too without any special code running + // before exec. + #[cfg(kill)] let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL"); - // With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too - // without any special code running before exec. - #[cfg(sig_ign)] + // We get SIG_IGN and the child does too without any special code running + // before exec. + #[cfg(error)] let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_IGN"); - // With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too - // without any special code running before exec. + // We get SIG_DFL and the child does too without any special code running + // before exec. #[cfg(inherit)] let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL"); diff --git a/tests/ui/runtime/on-broken-pipe/default.rs b/tests/ui/runtime/on-broken-pipe/default.rs new file mode 100644 index 00000000000..c10d1cfacc0 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/default.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe=default +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/default.stderr b/tests/ui/runtime/on-broken-pipe/default.stderr new file mode 100644 index 00000000000..b90d7566cbb --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/default.stderr @@ -0,0 +1,2 @@ +error: incorrect value `default` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs b/tests/ui/runtime/on-broken-pipe/error.rs similarity index 50% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs rename to tests/ui/runtime/on-broken-pipe/error.rs index b0044f5e919..ab2036c2f41 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs +++ b/tests/ui/runtime/on-broken-pipe/error.rs @@ -1,12 +1,10 @@ -//@ revisions: with_feature without_feature //@ run-pass //@ aux-build:sigpipe-utils.rs - -#![cfg_attr(with_feature, feature(unix_sigpipe))] +//@ compile-flags: -Zon-broken-pipe=error fn main() { extern crate sigpipe_utils; - // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used + // `-Zon-broken-pipe=error` is active, so we expect SIGPIPE to be ignored. sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/tests/ui/runtime/on-broken-pipe/inherit.rs similarity index 73% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs rename to tests/ui/runtime/on-broken-pipe/inherit.rs index 3e63349edb7..64909b73528 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs +++ b/tests/ui/runtime/on-broken-pipe/inherit.rs @@ -3,20 +3,20 @@ //@ aux-bin: assert-inherit-sig_dfl.rs //@ aux-bin: assert-inherit-sig_ign.rs //@ run-pass +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(rustc_private, unix_sigpipe)] +#![feature(rustc_private)] extern crate libc; // By default the Rust runtime resets SIGPIPE to SIG_DFL before exec'ing child -// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See +// processes so opt-out of that with `-Zon-broken-pipe=kill`. See // https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384 -#[unix_sigpipe = "sig_dfl"] fn main() { - // First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"]. + // First expect SIG_DFL in a child process with -`Zon-broken-pipe=inherit`. assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl"); - // With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN. + // With SIG_IGN we expect `-Zon-broken-pipe=inherit` to also get SIG_IGN. unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs b/tests/ui/runtime/on-broken-pipe/kill.rs similarity index 60% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs rename to tests/ui/runtime/on-broken-pipe/kill.rs index 30f2a9b1430..5dace6f1c6f 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs +++ b/tests/ui/runtime/on-broken-pipe/kill.rs @@ -1,13 +1,11 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] fn main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead + // `-Zon-broken-pipe=kill` is active, so SIGPIPE shall NOT be ignored, instead // the default handler shall be installed sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs new file mode 100644 index 00000000000..2273291bfa7 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr b/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr new file mode 100644 index 00000000000..3d3e12d303c --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr @@ -0,0 +1,2 @@ +error: unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit` (Z on-broken-pipe=) + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_ign.rs b/tests/ui/runtime/on-broken-pipe/not-used.rs similarity index 50% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_ign.rs rename to tests/ui/runtime/on-broken-pipe/not-used.rs index ccd6c678660..e31236f2b3d 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_ign.rs +++ b/tests/ui/runtime/on-broken-pipe/not-used.rs @@ -1,13 +1,9 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_ign"] fn main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring - // SIGPIPE shall be in effect + // SIGPIPE shall be ignored since `-Zon-broken-pipe` is not used sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs similarity index 69% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs rename to tests/ui/runtime/on-broken-pipe/with-rustc_main.rs index 02a3f48f3b3..c1731200038 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs +++ b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs @@ -1,15 +1,14 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(unix_sigpipe)] #![feature(rustc_attrs)] -#[unix_sigpipe = "sig_dfl"] #[rustc_main] fn rustc_main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be + // `-Zon-broken-pipe=kill` is active, so SIGPIPE handler shall be // SIG_DFL. Note that we have a #[rustc_main], but it should still work. sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs new file mode 100644 index 00000000000..14d0ac56b5a --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe=wrong +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr new file mode 100644 index 00000000000..3635418c845 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr @@ -0,0 +1,2 @@ +error: incorrect value `wrong` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected +