Skip to content

Commit 8c6ce6b

Browse files
committedSep 2, 2022
Auto merge of #97802 - Enselic:add-no_ignore_sigkill-feature, r=joshtriplett
Support `#[unix_sigpipe = "inherit|sig_dfl"]` on `fn main()` to prevent ignoring `SIGPIPE` When enabled, programs don't have to explicitly handle `ErrorKind::BrokenPipe` any longer. Currently, the program ```rust fn main() { loop { println!("hello world"); } } ``` will print an error if used with a short-lived pipe, e.g. % ./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 by enabling `#[unix_sigpipe = "sig_dfl"]` like this ```rust #![feature(unix_sigpipe)] #[unix_sigpipe = "sig_dfl"] fn main() { loop { println!("hello world"); } } ``` there is no error, because `SIGPIPE` will not be ignored and thus the program will be killed appropriately: % ./main | head -n 1 hello world The current libstd behaviour of ignoring `SIGPIPE` before `fn main()` can be explicitly requested by using `#[unix_sigpipe = "sig_ign"]`. With `#[unix_sigpipe = "inherit"]`, no change at all is made to `SIGPIPE`, which typically means the behaviour will be the same as `#[unix_sigpipe = "sig_dfl"]`. See #62569 and referenced issues for discussions regarding the `SIGPIPE` problem itself See the [this](https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Proposal.3A.20First.20step.20towards.20solving.20the.20SIGPIPE.20problem) Zulip topic for more discussions, including about this PR. Tracking issue: #97889
2 parents 9ba169a + 3810d4a commit 8c6ce6b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+482
-43
lines changed
 

‎compiler/rustc_codegen_cranelift/src/main_shim.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_hir::LangItem;
22
use rustc_middle::ty::subst::GenericArg;
33
use rustc_middle::ty::AssocKind;
4-
use rustc_session::config::EntryFnType;
4+
use rustc_session::config::{sigpipe, EntryFnType};
55
use rustc_span::symbol::Ident;
66

77
use crate::prelude::*;
@@ -15,12 +15,12 @@ pub(crate) fn maybe_create_entry_wrapper(
1515
is_jit: bool,
1616
is_primary_cgu: bool,
1717
) {
18-
let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
18+
let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
1919
Some((def_id, entry_ty)) => (
2020
def_id,
2121
match entry_ty {
22-
EntryFnType::Main => true,
23-
EntryFnType::Start => false,
22+
EntryFnType::Main { sigpipe } => (true, sigpipe),
23+
EntryFnType::Start => (false, sigpipe::DEFAULT),
2424
},
2525
),
2626
None => return,
@@ -35,7 +35,7 @@ pub(crate) fn maybe_create_entry_wrapper(
3535
return;
3636
}
3737

38-
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);
38+
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
3939

4040
fn create_entry_fn(
4141
tcx: TyCtxt<'_>,
@@ -44,6 +44,7 @@ pub(crate) fn maybe_create_entry_wrapper(
4444
rust_main_def_id: DefId,
4545
ignore_lang_start_wrapper: bool,
4646
is_main_fn: bool,
47+
sigpipe: u8,
4748
) {
4849
let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
4950
// Given that `main()` has no arguments,
@@ -83,6 +84,7 @@ pub(crate) fn maybe_create_entry_wrapper(
8384
bcx.switch_to_block(block);
8485
let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
8586
let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
87+
let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
8688

8789
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
8890

@@ -143,7 +145,8 @@ pub(crate) fn maybe_create_entry_wrapper(
143145
let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
144146

145147
let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
146-
let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
148+
let call_inst =
149+
bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
147150
bcx.inst_results(call_inst)[0]
148151
} else {
149152
// using user-defined start fn

‎compiler/rustc_codegen_ssa/src/base.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,14 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
389389

390390
let main_llfn = cx.get_fn_addr(instance);
391391

392-
let use_start_lang_item = EntryFnType::Start != entry_type;
393-
let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
392+
let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
394393
return Some(entry_fn);
395394

396395
fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
397396
cx: &'a Bx::CodegenCx,
398397
rust_main: Bx::Value,
399398
rust_main_def_id: DefId,
400-
use_start_lang_item: bool,
399+
entry_type: EntryFnType,
401400
) -> Bx::Function {
402401
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
403402
// depending on whether the target needs `argc` and `argv` to be passed in.
@@ -442,7 +441,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
442441
let i8pp_ty = cx.type_ptr_to(cx.type_i8p());
443442
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
444443

445-
let (start_fn, start_ty, args) = if use_start_lang_item {
444+
let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
446445
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
447446
let start_fn = cx.get_fn_addr(
448447
ty::Instance::resolve(
@@ -454,8 +453,13 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
454453
.unwrap()
455454
.unwrap(),
456455
);
457-
let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty], isize_ty);
458-
(start_fn, start_ty, vec![rust_main, arg_argc, arg_argv])
456+
457+
let i8_ty = cx.type_i8();
458+
let arg_sigpipe = bx.const_u8(sigpipe);
459+
460+
let start_ty =
461+
cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty, i8_ty], isize_ty);
462+
(start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
459463
} else {
460464
debug!("using user-defined start fn");
461465
let start_ty = cx.type_func(&[isize_ty, i8pp_ty], isize_ty);

0 commit comments

Comments
 (0)
Please sign in to comment.