mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std.Io.Threaded: install and cleanup signal handlers
rather than in start code. delete std.options.keep_sig_io and std.options.keep_sig_pipe
This commit is contained in:
parent
b863f2548b
commit
05b28409e7
4 changed files with 38 additions and 37 deletions
|
|
@ -26,8 +26,13 @@ threads: std.ArrayListUnmanaged(std.Thread),
|
|||
stack_size: usize,
|
||||
cpu_count: std.Thread.CpuCountError!usize,
|
||||
concurrent_count: usize,
|
||||
|
||||
wsa: if (is_windows) Wsa else struct {} = .{},
|
||||
|
||||
have_signal_handler: bool,
|
||||
old_sig_io: if (have_sig_io) posix.Sigaction else void,
|
||||
old_sig_pipe: if (have_sig_pipe) posix.Sigaction else void,
|
||||
|
||||
threadlocal var current_closure: ?*Closure = null;
|
||||
|
||||
const max_iovecs_len = 8;
|
||||
|
|
@ -104,23 +109,46 @@ pub fn init(
|
|||
.stack_size = std.Thread.SpawnConfig.default_stack_size,
|
||||
.cpu_count = std.Thread.getCpuCount(),
|
||||
.concurrent_count = 0,
|
||||
.old_sig_io = undefined,
|
||||
.old_sig_pipe = undefined,
|
||||
.have_signal_handler = false,
|
||||
};
|
||||
|
||||
if (t.cpu_count) |n| {
|
||||
t.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {};
|
||||
} else |_| {}
|
||||
|
||||
if (posix.Sigaction != void) {
|
||||
// This causes sending `posix.SIG.IO` to thread to interrupt blocking
|
||||
// syscalls, returning `posix.E.INTR`.
|
||||
const act: posix.Sigaction = .{
|
||||
.handler = .{ .handler = doNothingSignalHandler },
|
||||
.mask = posix.sigemptyset(),
|
||||
.flags = 0,
|
||||
};
|
||||
if (have_sig_io) posix.sigaction(.IO, &act, &t.old_sig_io);
|
||||
if (have_sig_pipe) posix.sigaction(.PIPE, &act, &t.old_sig_pipe);
|
||||
t.have_signal_handler = true;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/// Statically initialize such that calls to `Io.VTable.concurrent` will fail
|
||||
/// with `error.ConcurrencyUnavailable`.
|
||||
///
|
||||
/// When initialized this way, `deinit` is safe, but unnecessary to call.
|
||||
/// When initialized this way:
|
||||
/// * cancel requests have no effect.
|
||||
/// * `deinit` is safe, but unnecessary to call.
|
||||
pub const init_single_threaded: Threaded = .{
|
||||
.allocator = .failing,
|
||||
.threads = .empty,
|
||||
.stack_size = std.Thread.SpawnConfig.default_stack_size,
|
||||
.cpu_count = 1,
|
||||
.concurrent_count = 0,
|
||||
.old_sig_io = undefined,
|
||||
.old_sig_pipe = undefined,
|
||||
.have_signal_handler = false,
|
||||
};
|
||||
|
||||
pub fn deinit(t: *Threaded) void {
|
||||
|
|
@ -130,6 +158,10 @@ pub fn deinit(t: *Threaded) void {
|
|||
if (is_windows and t.wsa.status == .initialized) {
|
||||
if (ws2_32.WSACleanup() != 0) recoverableOsBugDetected();
|
||||
}
|
||||
if (posix.Sigaction != void and t.have_signal_handler) {
|
||||
if (have_sig_io) posix.sigaction(.IO, &t.old_sig_io, null);
|
||||
if (have_sig_pipe) posix.sigaction(.PIPE, &t.old_sig_pipe, null);
|
||||
}
|
||||
t.* = undefined;
|
||||
}
|
||||
|
||||
|
|
@ -338,6 +370,8 @@ const have_preadv = switch (native_os) {
|
|||
.windows, .haiku, .serenity => false, // 💩💩💩
|
||||
else => true,
|
||||
};
|
||||
const have_sig_io = posix.SIG != void and @hasField(posix.SIG, "IO");
|
||||
const have_sig_pipe = posix.SIG != void and @hasField(posix.SIG, "PIPE");
|
||||
|
||||
const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;
|
||||
const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat;
|
||||
|
|
@ -6115,6 +6149,8 @@ fn initializeWsa(t: *Threaded) error{NetworkDown}!void {
|
|||
return error.NetworkDown;
|
||||
}
|
||||
|
||||
fn doNothingSignalHandler(_: posix.SIG) callconv(.c) void {}
|
||||
|
||||
test {
|
||||
_ = @import("Threaded/test.zig");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ else switch (native_os) {
|
|||
pub const mode_t = u0;
|
||||
pub const ino_t = void;
|
||||
pub const IFNAMESIZE = {};
|
||||
pub const SIG = void;
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -651,7 +651,6 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
|
|||
std.os.argv = argv[0..argc];
|
||||
std.os.environ = envp;
|
||||
|
||||
maybeIgnoreSignals();
|
||||
std.debug.maybeEnableSegfaultHandler();
|
||||
|
||||
return callMain();
|
||||
|
|
@ -756,23 +755,3 @@ pub fn call_wWinMain() std.os.windows.INT {
|
|||
// second parameter hPrevInstance, MSDN: "This parameter is always NULL"
|
||||
return root.wWinMain(hInstance, null, lpCmdLine, nCmdShow);
|
||||
}
|
||||
|
||||
fn maybeIgnoreSignals() void {
|
||||
const posix = std.posix;
|
||||
if (posix.Sigaction == void) return;
|
||||
const act: posix.Sigaction = .{
|
||||
// Set handler to a noop function instead of `IGN` to prevent
|
||||
// leaking signal disposition to a child process.
|
||||
.handler = .{ .handler = noopSigHandler },
|
||||
.mask = posix.sigemptyset(),
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
if (@hasField(posix.SIG, "IO") and !std.options.keep_sig_io)
|
||||
posix.sigaction(.IO, &act, null);
|
||||
|
||||
if (@hasField(posix.SIG, "PIPE") and !std.options.keep_sig_pipe)
|
||||
posix.sigaction(.PIPE, &act, null);
|
||||
}
|
||||
|
||||
fn noopSigHandler(_: std.posix.SIG) callconv(.c) void {}
|
||||
|
|
|
|||
|
|
@ -144,21 +144,6 @@ pub const Options = struct {
|
|||
|
||||
crypto_fork_safety: bool = true,
|
||||
|
||||
keep_sig_io: bool = false,
|
||||
|
||||
/// By default Zig disables SIGPIPE by setting a "no-op" handler for it. Set this option
|
||||
/// to `true` to prevent that.
|
||||
///
|
||||
/// Note that we use a "no-op" handler instead of SIG_IGN because it will not be inherited by
|
||||
/// any child process.
|
||||
///
|
||||
/// SIGPIPE is triggered when a process attempts to write to a broken pipe. By default, SIGPIPE
|
||||
/// will terminate the process instead of exiting. It doesn't trigger the panic handler so in many
|
||||
/// cases it's unclear why the process was terminated. By capturing SIGPIPE instead, functions that
|
||||
/// write to broken pipes will return the EPIPE error (error.BrokenPipe) and the program can handle
|
||||
/// it like any other error.
|
||||
keep_sig_pipe: bool = false,
|
||||
|
||||
/// By default, std.http.Client will support HTTPS connections. Set this option to `true` to
|
||||
/// disable TLS support.
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue