Commit 05b28409e7
Changed files (4)
lib
lib/std/Io/Threaded.zig
@@ -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");
}
lib/std/posix.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;
},
};
lib/std/start.zig
@@ -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 {}
lib/std/std.zig
@@ -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.
///