authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2022-07-02 09:40:24-06:00
committergravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2023-02-17 09:08:41-07:00
logc02ced4d346656abefa4cccfbdebf5dd27b326e5
tree4fb193730a79dc303b5c68e451f1d11ac5adce2e
parent3f7e9ff597a3514bb1c4f1900027c40682ac9f13

ignore SIGPIPE by default


2 files changed, 46 insertions(+), 0 deletions(-)

lib/std/os.zig+45
...@@ -7056,3 +7056,48 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {...@@ -7056,3 +7056,48 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
7056 else => |err| return unexpectedErrno(err),7056 else => |err| return unexpectedErrno(err),
7057 };7057 };
7058}7058}
7059
7060/// Whether or not the current target support SIGPIPE
7061pub const have_sigpipe_support = switch (builtin.os.tag) {
7062 .linux,
7063 .macos,
7064 .netbsd,
7065 .solaris,
7066 .freebsd,
7067 .openbsd,
7068 => true,
7069 else => false,
7070};
7071
7072pub const keep_sigpipe: bool = if (@hasDecl(root, "keep_sigpipe"))
7073 root.keep_sigpipe
7074else
7075 false;
7076
7077/// This function will tell the kernel to ignore SIGPIPE rather than terminate
7078/// the process. This function is automatically called in `start.zig` before
7079/// `main`. This behavior can be disabled by adding this to your root module:
7080///
7081/// pub const keep_sigpipe = true;
7082///
7083/// SIGPIPE is triggered when a process attempts to write to a broken pipe.
7084/// By default, SIGPIPE will terminate the process without giving the program
7085/// an opportunity to handle the situation. Unlike a segfault, it doesn't
7086/// trigger the panic handler so all the developer sees is that the program
7087/// terminated with no indication as to why.
7088///
7089/// By telling the kernel to instead ignore SIGPIPE, writes to broken pipes
7090/// will return the EPIPE error (error.BrokenPipe) and the program can handle
7091/// it like any other error.
7092pub fn maybeIgnoreSigpipe() void {
7093 if (have_sigpipe_support and !keep_sigpipe) {
7094 const act = Sigaction{
7095 .handler = .{ .sigaction = SIG.IGN },
7096 .mask = empty_sigset,
7097 .flags = SA.SIGINFO,
7098 };
7099 sigaction(SIG.PIPE, &act, null) catch |err| std.debug.panic("ignore SIGPIPE failed with '{s}'" ++
7100 ", add `pub const keep_sigpipe = true;` to your root module" ++
7101 " or adjust have_sigpipe_support in std/os.zig", .{@errorName(err)});
7102 }
7103}
lib/std/start.zig+1
...@@ -496,6 +496,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {...@@ -496,6 +496,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
496 std.os.environ = envp;496 std.os.environ = envp;
497497
498 std.debug.maybeEnableSegfaultHandler();498 std.debug.maybeEnableSegfaultHandler();
499 std.os.maybeIgnoreSigpipe();
499500
500 return initEventLoopAndCallMain();501 return initEventLoopAndCallMain();
501}502}