| author | |
| committer | |
| log | ad9cb401124e4b2d59e49bed2736aad7813e4f1d |
| tree | 7bafd4a5dac886e67bb8f63ecfa22ae3bb2084c1 |
| parent | 971d19a3b2ca97b9acd00d74556a57a335898ed8 |
| parent | a55ecd7532e7ae015afe5cb5bc16b89376a4bf56 |
| signature |
Split glibc and linux sigset_t ABIs and the accessor functions22 files changed, 393 insertions(+), 155 deletions(-)
lib/std/Progress.zig+2-2| ... | @@ -410,9 +410,9 @@ pub fn start(options: Options) Node { | ... | @@ -410,9 +410,9 @@ pub fn start(options: Options) Node { |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | if (have_sigwinch) { | 412 | if (have_sigwinch) { |
| 413 | var act: posix.Sigaction = .{ | 413 | const act: posix.Sigaction = .{ |
| 414 | .handler = .{ .sigaction = handleSigWinch }, | 414 | .handler = .{ .sigaction = handleSigWinch }, |
| 415 | .mask = posix.empty_sigset, | 415 | .mask = posix.sigemptyset(), |
| 416 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART), | 416 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART), |
| 417 | }; | 417 | }; |
| 418 | posix.sigaction(posix.SIG.WINCH, &act, null); | 418 | posix.sigaction(posix.SIG.WINCH, &act, null); |
lib/std/c.zig+34-19| ... | @@ -3115,6 +3115,21 @@ pub const SYS = switch (native_os) { | ... | @@ -3115,6 +3115,21 @@ pub const SYS = switch (native_os) { |
| 3115 | .linux => linux.SYS, | 3115 | .linux => linux.SYS, |
| 3116 | else => void, | 3116 | else => void, |
| 3117 | }; | 3117 | }; |
| 3118 | |||
| 3119 | /// A common format for the Sigaction struct across a variety of Linux flavors. | ||
| 3120 | const common_linux_Sigaction = extern struct { | ||
| 3121 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; | ||
| 3122 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; | ||
| 3123 | |||
| 3124 | handler: extern union { | ||
| 3125 | handler: ?handler_fn, | ||
| 3126 | sigaction: ?sigaction_fn, | ||
| 3127 | }, | ||
| 3128 | mask: sigset_t, | ||
| 3129 | flags: c_uint, | ||
| 3130 | restorer: ?*const fn () callconv(.c) void = null, // C library will fill this in | ||
| 3131 | }; | ||
| 3132 | |||
| 3118 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. | 3133 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 3119 | pub const Sigaction = switch (native_os) { | 3134 | pub const Sigaction = switch (native_os) { |
| 3120 | .linux => switch (native_arch) { | 3135 | .linux => switch (native_arch) { |
| ... | @@ -3123,7 +3138,7 @@ pub const Sigaction = switch (native_os) { | ... | @@ -3123,7 +3138,7 @@ pub const Sigaction = switch (native_os) { |
| 3123 | .mips64, | 3138 | .mips64, |
| 3124 | .mips64el, | 3139 | .mips64el, |
| 3125 | => if (builtin.target.abi.isMusl()) | 3140 | => if (builtin.target.abi.isMusl()) |
| 3126 | linux.Sigaction | 3141 | common_linux_Sigaction |
| 3127 | else if (builtin.target.ptrBitWidth() == 64) extern struct { | 3142 | else if (builtin.target.ptrBitWidth() == 64) extern struct { |
| 3128 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; | 3143 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; |
| 3129 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; | 3144 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; |
| ... | @@ -3160,8 +3175,8 @@ pub const Sigaction = switch (native_os) { | ... | @@ -3160,8 +3175,8 @@ pub const Sigaction = switch (native_os) { |
| 3160 | flags: c_uint, | 3175 | flags: c_uint, |
| 3161 | restorer: ?*const fn () callconv(.c) void = null, | 3176 | restorer: ?*const fn () callconv(.c) void = null, |
| 3162 | mask: sigset_t, | 3177 | mask: sigset_t, |
| 3163 | } else linux.Sigaction, | 3178 | } else common_linux_Sigaction, |
| 3164 | else => linux.Sigaction, | 3179 | else => common_linux_Sigaction, |
| 3165 | }, | 3180 | }, |
| 3166 | .emscripten => emscripten.Sigaction, | 3181 | .emscripten => emscripten.Sigaction, |
| 3167 | .netbsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct { | 3182 | .netbsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct { |
| ... | @@ -4518,27 +4533,18 @@ pub const siginfo_t = switch (native_os) { | ... | @@ -4518,27 +4533,18 @@ pub const siginfo_t = switch (native_os) { |
| 4518 | else => void, | 4533 | else => void, |
| 4519 | }; | 4534 | }; |
| 4520 | pub const sigset_t = switch (native_os) { | 4535 | pub const sigset_t = switch (native_os) { |
| 4521 | .linux => linux.sigset_t, | 4536 | .linux => [1024 / @bitSizeOf(c_ulong)]c_ulong, // glibc and musl present a 1024-bit sigset_t, while kernel's is 128-bit or less. |
| 4522 | .emscripten => emscripten.sigset_t, | 4537 | .emscripten => emscripten.sigset_t, |
| 4523 | // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L19 | 4538 | // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L19 |
| 4524 | .openbsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => u32, | 4539 | .openbsd, .serenity => u32, |
| 4540 | .macos, .ios, .tvos, .watchos, .visionos => darwin.sigset_t, | ||
| 4525 | .dragonfly, .netbsd, .solaris, .illumos, .freebsd => extern struct { | 4541 | .dragonfly, .netbsd, .solaris, .illumos, .freebsd => extern struct { |
| 4526 | __bits: [SIG.WORDS]u32, | 4542 | __bits: [SIG.WORDS]u32, |
| 4527 | }, | 4543 | }, |
| 4528 | .haiku => u64, | 4544 | .haiku => u64, |
| 4529 | else => u0, | 4545 | else => u0, |
| 4530 | }; | 4546 | }; |
| 4531 | pub const empty_sigset: sigset_t = switch (native_os) { | 4547 | |
| 4532 | .linux => linux.empty_sigset, | ||
| 4533 | .emscripten => emscripten.empty_sigset, | ||
| 4534 | .dragonfly, .netbsd, .solaris, .illumos, .freebsd => .{ .__bits = [_]u32{0} ** SIG.WORDS }, | ||
| 4535 | else => 0, | ||
| 4536 | }; | ||
| 4537 | pub const filled_sigset = switch (native_os) { | ||
| 4538 | .linux => linux.filled_sigset, | ||
| 4539 | .haiku => ~@as(sigset_t, 0), | ||
| 4540 | else => 0, | ||
| 4541 | }; | ||
| 4542 | pub const sigval = switch (native_os) { | 4548 | pub const sigval = switch (native_os) { |
| 4543 | .linux => linux.sigval, | 4549 | .linux => linux.sigval, |
| 4544 | // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L22-L25 | 4550 | // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L22-L25 |
| ... | @@ -6665,7 +6671,7 @@ pub const timezone = switch (native_os) { | ... | @@ -6665,7 +6671,7 @@ pub const timezone = switch (native_os) { |
| 6665 | }; | 6671 | }; |
| 6666 | 6672 | ||
| 6667 | pub const ucontext_t = switch (native_os) { | 6673 | pub const ucontext_t = switch (native_os) { |
| 6668 | .linux => linux.ucontext_t, | 6674 | .linux => linux.ucontext_t, // std.os.linux.ucontext_t is currently glibc-compatible, but it should probably not be. |
| 6669 | .emscripten => emscripten.ucontext_t, | 6675 | .emscripten => emscripten.ucontext_t, |
| 6670 | .macos, .ios, .tvos, .watchos, .visionos => extern struct { | 6676 | .macos, .ios, .tvos, .watchos, .visionos => extern struct { |
| 6671 | onstack: c_int, | 6677 | onstack: c_int, |
| ... | @@ -9596,6 +9602,7 @@ pub const NSIG = switch (native_os) { | ... | @@ -9596,6 +9602,7 @@ pub const NSIG = switch (native_os) { |
| 9596 | .windows => 23, | 9602 | .windows => 23, |
| 9597 | .haiku => 65, | 9603 | .haiku => 65, |
| 9598 | .netbsd, .freebsd => 32, | 9604 | .netbsd, .freebsd => 32, |
| 9605 | .macos => darwin.NSIG, | ||
| 9599 | .solaris, .illumos => 75, | 9606 | .solaris, .illumos => 75, |
| 9600 | // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 | 9607 | // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 |
| 9601 | .openbsd, .serenity => 33, | 9608 | .openbsd, .serenity => 33, |
| ... | @@ -10345,6 +10352,11 @@ pub const sigfillset = switch (native_os) { | ... | @@ -10345,6 +10352,11 @@ pub const sigfillset = switch (native_os) { |
| 10345 | else => private.sigfillset, | 10352 | else => private.sigfillset, |
| 10346 | }; | 10353 | }; |
| 10347 | 10354 | ||
| 10355 | pub const sigaddset = private.sigaddset; | ||
| 10356 | pub const sigemptyset = private.sigemptyset; | ||
| 10357 | pub const sigdelset = private.sigdelset; | ||
| 10358 | pub const sigismember = private.sigismember; | ||
| 10359 | |||
| 10348 | pub const sigprocmask = switch (native_os) { | 10360 | pub const sigprocmask = switch (native_os) { |
| 10349 | .netbsd => private.__sigprocmask14, | 10361 | .netbsd => private.__sigprocmask14, |
| 10350 | else => private.sigprocmask, | 10362 | else => private.sigprocmask, |
| ... | @@ -11025,7 +11037,6 @@ pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np; | ... | @@ -11025,7 +11037,6 @@ pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np; |
| 11025 | pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np; | 11037 | pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np; |
| 11026 | pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np; | 11038 | pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np; |
| 11027 | pub const ptrace = darwin.ptrace; | 11039 | pub const ptrace = darwin.ptrace; |
| 11028 | pub const sigaddset = darwin.sigaddset; | ||
| 11029 | pub const task_for_pid = darwin.task_for_pid; | 11040 | pub const task_for_pid = darwin.task_for_pid; |
| 11030 | pub const task_get_exception_ports = darwin.task_get_exception_ports; | 11041 | pub const task_get_exception_ports = darwin.task_get_exception_ports; |
| 11031 | pub const task_info = darwin.task_info; | 11042 | pub const task_info = darwin.task_info; |
| ... | @@ -11148,7 +11159,11 @@ const private = struct { | ... | @@ -11148,7 +11159,11 @@ const private = struct { |
| 11148 | extern "c" fn sched_yield() c_int; | 11159 | extern "c" fn sched_yield() c_int; |
| 11149 | extern "c" fn sendfile(out_fd: fd_t, in_fd: fd_t, offset: ?*off_t, count: usize) isize; | 11160 | extern "c" fn sendfile(out_fd: fd_t, in_fd: fd_t, offset: ?*off_t, count: usize) isize; |
| 11150 | extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; | 11161 | extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; |
| 11151 | extern "c" fn sigfillset(set: ?*sigset_t) void; | 11162 | extern "c" fn sigdelset(set: ?*sigset_t, signo: c_int) c_int; |
| 11163 | extern "c" fn sigaddset(set: ?*sigset_t, signo: c_int) c_int; | ||
| 11164 | extern "c" fn sigfillset(set: ?*sigset_t) c_int; | ||
| 11165 | extern "c" fn sigemptyset(set: ?*sigset_t) c_int; | ||
| 11166 | extern "c" fn sigismember(set: ?*const sigset_t, signo: c_int) c_int; | ||
| 11152 | extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; | 11167 | extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 11153 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; | 11168 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 11154 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; | 11169 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; |
lib/std/c/darwin.zig+5-4| ... | @@ -10,7 +10,6 @@ const mode_t = std.c.mode_t; | ... | @@ -10,7 +10,6 @@ const mode_t = std.c.mode_t; |
| 10 | const off_t = std.c.off_t; | 10 | const off_t = std.c.off_t; |
| 11 | const pid_t = std.c.pid_t; | 11 | const pid_t = std.c.pid_t; |
| 12 | const pthread_attr_t = std.c.pthread_attr_t; | 12 | const pthread_attr_t = std.c.pthread_attr_t; |
| 13 | const sigset_t = std.c.sigset_t; | ||
| 14 | const timespec = std.c.timespec; | 13 | const timespec = std.c.timespec; |
| 15 | const sf_hdtr = std.c.sf_hdtr; | 14 | const sf_hdtr = std.c.sf_hdtr; |
| 16 | 15 | ||
| ... | @@ -840,9 +839,11 @@ pub extern "c" fn sendfile( | ... | @@ -840,9 +839,11 @@ pub extern "c" fn sendfile( |
| 840 | flags: u32, | 839 | flags: u32, |
| 841 | ) c_int; | 840 | ) c_int; |
| 842 | 841 | ||
| 843 | pub fn sigaddset(set: *sigset_t, signo: u5) void { | 842 | // https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74 |
| 844 | set.* |= @as(u32, 1) << (signo - 1); | 843 | pub const sigset_t = u32; |
| 845 | } | 844 | |
| 845 | // https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/signal.h#L76 | ||
| 846 | pub const NSIG = 32; | ||
| 846 | 847 | ||
| 847 | pub const qos_class_t = enum(c_uint) { | 848 | pub const qos_class_t = enum(c_uint) { |
| 848 | /// highest priority QOS class for critical tasks | 849 | /// highest priority QOS class for critical tasks |
lib/std/debug.zig+4-5| ... | @@ -1387,12 +1387,11 @@ pub fn attachSegfaultHandler() void { | ... | @@ -1387,12 +1387,11 @@ pub fn attachSegfaultHandler() void { |
| 1387 | windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); | 1387 | windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); |
| 1388 | return; | 1388 | return; |
| 1389 | } | 1389 | } |
| 1390 | var act = posix.Sigaction{ | 1390 | const act = posix.Sigaction{ |
| 1391 | .handler = .{ .sigaction = handleSegfaultPosix }, | 1391 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 1392 | .mask = posix.empty_sigset, | 1392 | .mask = posix.sigemptyset(), |
| 1393 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), | 1393 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), |
| 1394 | }; | 1394 | }; |
| 1395 | |||
| 1396 | updateSegfaultHandler(&act); | 1395 | updateSegfaultHandler(&act); |
| 1397 | } | 1396 | } |
| 1398 | 1397 | ||
| ... | @@ -1404,9 +1403,9 @@ fn resetSegfaultHandler() void { | ... | @@ -1404,9 +1403,9 @@ fn resetSegfaultHandler() void { |
| 1404 | } | 1403 | } |
| 1405 | return; | 1404 | return; |
| 1406 | } | 1405 | } |
| 1407 | var act = posix.Sigaction{ | 1406 | const act = posix.Sigaction{ |
| 1408 | .handler = .{ .handler = posix.SIG.DFL }, | 1407 | .handler = .{ .handler = posix.SIG.DFL }, |
| 1409 | .mask = posix.empty_sigset, | 1408 | .mask = posix.sigemptyset(), |
| 1410 | .flags = 0, | 1409 | .flags = 0, |
| 1411 | }; | 1410 | }; |
| 1412 | updateSegfaultHandler(&act); | 1411 | updateSegfaultHandler(&act); |
lib/std/os/emscripten.zig+3-1| ... | @@ -560,7 +560,9 @@ pub const Sigaction = extern struct { | ... | @@ -560,7 +560,9 @@ pub const Sigaction = extern struct { |
| 560 | }; | 560 | }; |
| 561 | 561 | ||
| 562 | pub const sigset_t = [1024 / 32]u32; | 562 | pub const sigset_t = [1024 / 32]u32; |
| 563 | pub const empty_sigset = [_]u32{0} ** @typeInfo(sigset_t).array.len; | 563 | pub fn sigemptyset() sigset_t { |
| 564 | return [_]u32{0} ** @typeInfo(sigset_t).array.len; | ||
| 565 | } | ||
| 564 | pub const siginfo_t = extern struct { | 566 | pub const siginfo_t = extern struct { |
| 565 | signo: i32, | 567 | signo: i32, |
| 566 | errno: i32, | 568 | errno: i32, |
lib/std/os/linux.zig+62-53| ... | @@ -1745,8 +1745,9 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* | ... | @@ -1745,8 +1745,9 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* |
| 1745 | return syscall4(.rt_sigprocmask, flags, @intFromPtr(set), @intFromPtr(oldset), NSIG / 8); | 1745 | return syscall4(.rt_sigprocmask, flags, @intFromPtr(set), @intFromPtr(oldset), NSIG / 8); |
| 1746 | } | 1746 | } |
| 1747 | 1747 | ||
| 1748 | pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { | 1748 | pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { |
| 1749 | assert(sig >= 1); | 1749 | assert(sig > 0); |
| 1750 | assert(sig < NSIG); | ||
| 1750 | assert(sig != SIG.KILL); | 1751 | assert(sig != SIG.KILL); |
| 1751 | assert(sig != SIG.STOP); | 1752 | assert(sig != SIG.STOP); |
| 1752 | 1753 | ||
| ... | @@ -1755,14 +1756,15 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact | ... | @@ -1755,14 +1756,15 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 1755 | const mask_size = @sizeOf(@TypeOf(ksa.mask)); | 1756 | const mask_size = @sizeOf(@TypeOf(ksa.mask)); |
| 1756 | 1757 | ||
| 1757 | if (act) |new| { | 1758 | if (act) |new| { |
| 1759 | // Zig needs to install our arch restorer function with any signal handler, so | ||
| 1760 | // must copy the Sigaction struct | ||
| 1758 | const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore; | 1761 | const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore; |
| 1759 | ksa = k_sigaction{ | 1762 | ksa = k_sigaction{ |
| 1760 | .handler = new.handler.handler, | 1763 | .handler = new.handler.handler, |
| 1761 | .flags = new.flags | SA.RESTORER, | 1764 | .flags = new.flags | SA.RESTORER, |
| 1762 | .mask = undefined, | 1765 | .mask = new.mask, |
| 1763 | .restorer = @ptrCast(restorer_fn), | 1766 | .restorer = @ptrCast(restorer_fn), |
| 1764 | }; | 1767 | }; |
| 1765 | @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask))); | ||
| 1766 | } | 1768 | } |
| 1767 | 1769 | ||
| 1768 | const ksa_arg = if (act != null) @intFromPtr(&ksa) else 0; | 1770 | const ksa_arg = if (act != null) @intFromPtr(&ksa) else 0; |
| ... | @@ -1777,8 +1779,8 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact | ... | @@ -1777,8 +1779,8 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 1777 | 1779 | ||
| 1778 | if (oact) |old| { | 1780 | if (oact) |old| { |
| 1779 | old.handler.handler = oldksa.handler; | 1781 | old.handler.handler = oldksa.handler; |
| 1780 | old.flags = @as(c_uint, @truncate(oldksa.flags)); | 1782 | old.flags = oldksa.flags; |
| 1781 | @memcpy(@as([*]u8, @ptrCast(&old.mask))[0..mask_size], @as([*]const u8, @ptrCast(&oldksa.mask))); | 1783 | old.mask = oldksa.mask; |
| 1782 | } | 1784 | } |
| 1783 | 1785 | ||
| 1784 | return 0; | 1786 | return 0; |
| ... | @@ -1786,25 +1788,35 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact | ... | @@ -1786,25 +1788,35 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 1786 | 1788 | ||
| 1787 | const usize_bits = @typeInfo(usize).int.bits; | 1789 | const usize_bits = @typeInfo(usize).int.bits; |
| 1788 | 1790 | ||
| 1789 | pub const sigset_t = [1024 / 32]u32; | 1791 | /// Defined as one greater than the largest defined signal number. |
| 1792 | pub const NSIG = if (is_mips) 128 else 65; | ||
| 1790 | 1793 | ||
| 1791 | const sigset_len = @typeInfo(sigset_t).array.len; | 1794 | /// Linux kernel's sigset_t. This is logically 64-bit on most |
| 1795 | /// architectures, but 128-bit on MIPS. Contrast with the 1024-bit | ||
| 1796 | /// sigset_t exported by the glibc and musl library ABIs. | ||
| 1797 | pub const sigset_t = [(NSIG - 1 + 7) / @bitSizeOf(SigsetElement)]SigsetElement; | ||
| 1792 | 1798 | ||
| 1793 | /// Empty set to initialize sigset_t instances from. | 1799 | const SigsetElement = c_ulong; |
| 1794 | pub const empty_sigset: sigset_t = [_]u32{0} ** sigset_len; | ||
| 1795 | 1800 | ||
| 1796 | pub const filled_sigset: sigset_t = [_]u32{0x7fff_ffff} ++ [_]u32{0} ** (sigset_len - 1); | 1801 | const sigset_len = @typeInfo(sigset_t).array.len; |
| 1797 | 1802 | ||
| 1798 | pub const all_mask: sigset_t = [_]u32{0xffff_ffff} ** sigset_len; | 1803 | /// Zig's version of sigemptyset. Returns initialized sigset_t. |
| 1804 | pub fn sigemptyset() sigset_t { | ||
| 1805 | return [_]SigsetElement{0} ** sigset_len; | ||
| 1806 | } | ||
| 1799 | 1807 | ||
| 1800 | fn sigset_bit_index(sig: usize) struct { word: usize, mask: u32 } { | 1808 | /// Zig's version of sigfillset. Returns initalized sigset_t. |
| 1809 | pub fn sigfillset() sigset_t { | ||
| 1810 | return [_]SigsetElement{~@as(SigsetElement, 0)} ** sigset_len; | ||
| 1811 | } | ||
| 1812 | |||
| 1813 | fn sigset_bit_index(sig: usize) struct { word: usize, mask: SigsetElement } { | ||
| 1801 | assert(sig > 0); | 1814 | assert(sig > 0); |
| 1802 | assert(sig < NSIG); | 1815 | assert(sig < NSIG); |
| 1803 | const bit = sig - 1; | 1816 | const bit = sig - 1; |
| 1804 | const shift = @as(u5, @truncate(bit % 32)); | ||
| 1805 | return .{ | 1817 | return .{ |
| 1806 | .word = bit / 32, | 1818 | .word = bit / @bitSizeOf(SigsetElement), |
| 1807 | .mask = @as(u32, 1) << shift, | 1819 | .mask = @as(SigsetElement, 1) << @truncate(bit % @bitSizeOf(SigsetElement)), |
| 1808 | }; | 1820 | }; |
| 1809 | } | 1821 | } |
| 1810 | 1822 | ||
| ... | @@ -3487,6 +3499,7 @@ pub const SIG = if (is_mips) struct { | ... | @@ -3487,6 +3499,7 @@ pub const SIG = if (is_mips) struct { |
| 3487 | pub const UNBLOCK = 2; | 3499 | pub const UNBLOCK = 2; |
| 3488 | pub const SETMASK = 3; | 3500 | pub const SETMASK = 3; |
| 3489 | 3501 | ||
| 3502 | // https://github.com/torvalds/linux/blob/ca91b9500108d4cf083a635c2e11c884d5dd20ea/arch/mips/include/uapi/asm/signal.h#L25 | ||
| 3490 | pub const HUP = 1; | 3503 | pub const HUP = 1; |
| 3491 | pub const INT = 2; | 3504 | pub const INT = 2; |
| 3492 | pub const QUIT = 3; | 3505 | pub const QUIT = 3; |
| ... | @@ -3494,33 +3507,32 @@ pub const SIG = if (is_mips) struct { | ... | @@ -3494,33 +3507,32 @@ pub const SIG = if (is_mips) struct { |
| 3494 | pub const TRAP = 5; | 3507 | pub const TRAP = 5; |
| 3495 | pub const ABRT = 6; | 3508 | pub const ABRT = 6; |
| 3496 | pub const IOT = ABRT; | 3509 | pub const IOT = ABRT; |
| 3497 | pub const BUS = 7; | 3510 | pub const EMT = 7; |
| 3498 | pub const FPE = 8; | 3511 | pub const FPE = 8; |
| 3499 | pub const KILL = 9; | 3512 | pub const KILL = 9; |
| 3500 | pub const USR1 = 10; | 3513 | pub const BUS = 10; |
| 3501 | pub const SEGV = 11; | 3514 | pub const SEGV = 11; |
| 3502 | pub const USR2 = 12; | 3515 | pub const SYS = 12; |
| 3503 | pub const PIPE = 13; | 3516 | pub const PIPE = 13; |
| 3504 | pub const ALRM = 14; | 3517 | pub const ALRM = 14; |
| 3505 | pub const TERM = 15; | 3518 | pub const TERM = 15; |
| 3506 | pub const STKFLT = 16; | 3519 | pub const USR1 = 16; |
| 3507 | pub const CHLD = 17; | 3520 | pub const USR2 = 17; |
| 3508 | pub const CONT = 18; | 3521 | pub const CHLD = 18; |
| 3509 | pub const STOP = 19; | 3522 | pub const PWR = 19; |
| 3510 | pub const TSTP = 20; | 3523 | pub const WINCH = 20; |
| 3511 | pub const TTIN = 21; | 3524 | pub const URG = 21; |
| 3512 | pub const TTOU = 22; | 3525 | pub const IO = 22; |
| 3513 | pub const URG = 23; | 3526 | pub const POLL = IO; |
| 3514 | pub const XCPU = 24; | 3527 | pub const STOP = 23; |
| 3515 | pub const XFSZ = 25; | 3528 | pub const TSTP = 24; |
| 3516 | pub const VTALRM = 26; | 3529 | pub const CONT = 25; |
| 3517 | pub const PROF = 27; | 3530 | pub const TTIN = 26; |
| 3518 | pub const WINCH = 28; | 3531 | pub const TTOU = 27; |
| 3519 | pub const IO = 29; | 3532 | pub const VTALRM = 28; |
| 3520 | pub const POLL = 29; | 3533 | pub const PROF = 29; |
| 3521 | pub const PWR = 30; | 3534 | pub const XCPU = 30; |
| 3522 | pub const SYS = 31; | 3535 | pub const XFZ = 31; |
| 3523 | pub const UNUSED = SIG.SYS; | ||
| 3524 | 3536 | ||
| 3525 | pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); | 3537 | pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); |
| 3526 | pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); | 3538 | pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); |
| ... | @@ -5479,38 +5491,33 @@ pub const TFD = switch (native_arch) { | ... | @@ -5479,38 +5491,33 @@ pub const TFD = switch (native_arch) { |
| 5479 | }, | 5491 | }, |
| 5480 | }; | 5492 | }; |
| 5481 | 5493 | ||
| 5482 | /// NSIG is the total number of signals defined. | ||
| 5483 | /// As signal numbers are sequential, NSIG is one greater than the largest defined signal number. | ||
| 5484 | pub const NSIG = if (is_mips) 128 else 65; | ||
| 5485 | |||
| 5486 | const k_sigaction_funcs = struct { | 5494 | const k_sigaction_funcs = struct { |
| 5487 | const handler = ?*align(1) const fn (i32) callconv(.c) void; | 5495 | const handler = ?*align(1) const fn (i32) callconv(.c) void; |
| 5488 | const restorer = *const fn () callconv(.c) void; | 5496 | const restorer = *const fn () callconv(.c) void; |
| 5489 | }; | 5497 | }; |
| 5490 | 5498 | ||
| 5499 | /// Kernel sigaction struct, as expected by the `rt_sigaction` syscall. Includes restorer. | ||
| 5491 | pub const k_sigaction = switch (native_arch) { | 5500 | pub const k_sigaction = switch (native_arch) { |
| 5492 | .mips, .mipsel => extern struct { | 5501 | .mips, .mipsel, .mips64, .mips64el => extern struct { |
| 5493 | flags: c_uint, | ||
| 5494 | handler: k_sigaction_funcs.handler, | ||
| 5495 | mask: [4]c_ulong, | ||
| 5496 | restorer: k_sigaction_funcs.restorer, | ||
| 5497 | }, | ||
| 5498 | .mips64, .mips64el => extern struct { | ||
| 5499 | flags: c_uint, | 5502 | flags: c_uint, |
| 5500 | handler: k_sigaction_funcs.handler, | 5503 | handler: k_sigaction_funcs.handler, |
| 5501 | mask: [2]c_ulong, | 5504 | mask: sigset_t, |
| 5502 | restorer: k_sigaction_funcs.restorer, | 5505 | restorer: k_sigaction_funcs.restorer, |
| 5503 | }, | 5506 | }, |
| 5504 | else => extern struct { | 5507 | else => extern struct { |
| 5505 | handler: k_sigaction_funcs.handler, | 5508 | handler: k_sigaction_funcs.handler, |
| 5506 | flags: c_ulong, | 5509 | flags: c_ulong, |
| 5507 | restorer: k_sigaction_funcs.restorer, | 5510 | restorer: k_sigaction_funcs.restorer, |
| 5508 | mask: [2]c_uint, | 5511 | mask: sigset_t, |
| 5509 | }, | 5512 | }, |
| 5510 | }; | 5513 | }; |
| 5511 | 5514 | ||
| 5515 | /// Kernel Sigaction wrapper for the actual ABI `k_sigaction`. The Zig | ||
| 5516 | /// linux.zig wrapper library still does some pre-processing on | ||
| 5517 | /// sigaction() calls (to add the `restorer` field). | ||
| 5518 | /// | ||
| 5512 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 5519 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 5513 | pub const Sigaction = extern struct { | 5520 | pub const Sigaction = struct { |
| 5514 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; | 5521 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; |
| 5515 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; | 5522 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; |
| 5516 | 5523 | ||
| ... | @@ -5519,8 +5526,10 @@ pub const Sigaction = extern struct { | ... | @@ -5519,8 +5526,10 @@ pub const Sigaction = extern struct { |
| 5519 | sigaction: ?sigaction_fn, | 5526 | sigaction: ?sigaction_fn, |
| 5520 | }, | 5527 | }, |
| 5521 | mask: sigset_t, | 5528 | mask: sigset_t, |
| 5522 | flags: c_uint, | 5529 | flags: switch (native_arch) { |
| 5523 | restorer: ?*const fn () callconv(.c) void = null, | 5530 | .mips, .mipsel, .mips64, .mips64el => c_uint, |
| 5531 | else => c_ulong, | ||
| 5532 | }, | ||
| 5524 | }; | 5533 | }; |
| 5525 | 5534 | ||
| 5526 | pub const SFD = struct { | 5535 | pub const SFD = struct { |
lib/std/os/linux/aarch64.zig+1-1| ... | @@ -289,7 +289,7 @@ pub const ucontext_t = extern struct { | ... | @@ -289,7 +289,7 @@ pub const ucontext_t = extern struct { |
| 289 | flags: usize, | 289 | flags: usize, |
| 290 | link: ?*ucontext_t, | 290 | link: ?*ucontext_t, |
| 291 | stack: stack_t, | 291 | stack: stack_t, |
| 292 | sigmask: sigset_t, | 292 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 293 | mcontext: mcontext_t, | 293 | mcontext: mcontext_t, |
| 294 | }; | 294 | }; |
| 295 | 295 |
lib/std/os/linux/arm.zig+1-1| ... | @@ -337,7 +337,7 @@ pub const ucontext_t = extern struct { | ... | @@ -337,7 +337,7 @@ pub const ucontext_t = extern struct { |
| 337 | link: ?*ucontext_t, | 337 | link: ?*ucontext_t, |
| 338 | stack: stack_t, | 338 | stack: stack_t, |
| 339 | mcontext: mcontext_t, | 339 | mcontext: mcontext_t, |
| 340 | sigmask: sigset_t, | 340 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 341 | regspace: [64]u64, | 341 | regspace: [64]u64, |
| 342 | }; | 342 | }; |
| 343 | 343 |
lib/std/os/linux/loongarch64.zig+1-2| ... | @@ -264,8 +264,7 @@ pub const ucontext_t = extern struct { | ... | @@ -264,8 +264,7 @@ pub const ucontext_t = extern struct { |
| 264 | flags: c_ulong, | 264 | flags: c_ulong, |
| 265 | link: ?*ucontext_t, | 265 | link: ?*ucontext_t, |
| 266 | stack: stack_t, | 266 | stack: stack_t, |
| 267 | sigmask: sigset_t, | 267 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 268 | _pad: [1024 / 8 - @sizeOf(sigset_t)]u8, | ||
| 269 | mcontext: mcontext_t, | 268 | mcontext: mcontext_t, |
| 270 | }; | 269 | }; |
| 271 | 270 |
lib/std/os/linux/powerpc.zig+1-1| ... | @@ -341,7 +341,7 @@ pub const ucontext_t = extern struct { | ... | @@ -341,7 +341,7 @@ pub const ucontext_t = extern struct { |
| 341 | stack: stack_t, | 341 | stack: stack_t, |
| 342 | pad: [7]i32, | 342 | pad: [7]i32, |
| 343 | regs: *mcontext_t, | 343 | regs: *mcontext_t, |
| 344 | sigmask: sigset_t, | 344 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 345 | pad2: [3]i32, | 345 | pad2: [3]i32, |
| 346 | mcontext: mcontext_t, | 346 | mcontext: mcontext_t, |
| 347 | }; | 347 | }; |
lib/std/os/linux/powerpc64.zig+1-1| ... | @@ -337,7 +337,7 @@ pub const ucontext_t = extern struct { | ... | @@ -337,7 +337,7 @@ pub const ucontext_t = extern struct { |
| 337 | flags: u32, | 337 | flags: u32, |
| 338 | link: ?*ucontext_t, | 338 | link: ?*ucontext_t, |
| 339 | stack: stack_t, | 339 | stack: stack_t, |
| 340 | sigmask: sigset_t, | 340 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 341 | mcontext: mcontext_t, | 341 | mcontext: mcontext_t, |
| 342 | }; | 342 | }; |
| 343 | 343 |
lib/std/os/linux/s390x.zig+1-1| ... | @@ -273,7 +273,7 @@ pub const ucontext_t = extern struct { | ... | @@ -273,7 +273,7 @@ pub const ucontext_t = extern struct { |
| 273 | link: ?*ucontext_t, | 273 | link: ?*ucontext_t, |
| 274 | stack: stack_t, | 274 | stack: stack_t, |
| 275 | mcontext: mcontext_t, | 275 | mcontext: mcontext_t, |
| 276 | sigmask: sigset_t, | 276 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 277 | }; | 277 | }; |
| 278 | 278 | ||
| 279 | pub const mcontext_t = extern struct { | 279 | pub const mcontext_t = extern struct { |
lib/std/os/linux/sparc64.zig+1-1| ... | @@ -454,7 +454,7 @@ pub const ucontext_t = extern struct { | ... | @@ -454,7 +454,7 @@ pub const ucontext_t = extern struct { |
| 454 | sigmask: u64, | 454 | sigmask: u64, |
| 455 | mcontext: mcontext_t, | 455 | mcontext: mcontext_t, |
| 456 | stack: stack_t, | 456 | stack: stack_t, |
| 457 | sigset: sigset_t, | 457 | sigset: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 458 | }; | 458 | }; |
| 459 | 459 | ||
| 460 | /// TODO | 460 | /// TODO |
lib/std/os/linux/test.zig+40-9| ... | @@ -126,7 +126,9 @@ test "fadvise" { | ... | @@ -126,7 +126,9 @@ test "fadvise" { |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | test "sigset_t" { | 128 | test "sigset_t" { |
| 129 | var sigset = linux.empty_sigset; | 129 | std.debug.assert(@sizeOf(linux.sigset_t) == (linux.NSIG / 8)); |
| 130 | |||
| 131 | var sigset = linux.sigemptyset(); | ||
| 130 | 132 | ||
| 131 | // See that none are set, then set each one, see that they're all set, then | 133 | // See that none are set, then set each one, see that they're all set, then |
| 132 | // remove them all, and then see that none are set. | 134 | // remove them all, and then see that none are set. |
| ... | @@ -138,7 +140,6 @@ test "sigset_t" { | ... | @@ -138,7 +140,6 @@ test "sigset_t" { |
| 138 | } | 140 | } |
| 139 | for (1..linux.NSIG) |i| { | 141 | for (1..linux.NSIG) |i| { |
| 140 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), true); | 142 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), true); |
| 141 | try expectEqual(linux.sigismember(&linux.empty_sigset, @truncate(i)), false); | ||
| 142 | } | 143 | } |
| 143 | for (1..linux.NSIG) |i| { | 144 | for (1..linux.NSIG) |i| { |
| 144 | linux.sigdelset(&sigset, @truncate(i)); | 145 | linux.sigdelset(&sigset, @truncate(i)); |
| ... | @@ -147,22 +148,52 @@ test "sigset_t" { | ... | @@ -147,22 +148,52 @@ test "sigset_t" { |
| 147 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), false); | 148 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), false); |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 151 | // Kernel sigset_t is either 2+ 32-bit values or 1+ 64-bit value(s). | ||
| 152 | const sigset_len = @typeInfo(linux.sigset_t).array.len; | ||
| 153 | const sigset_elemis64 = 64 == @bitSizeOf(@typeInfo(linux.sigset_t).array.child); | ||
| 154 | |||
| 150 | linux.sigaddset(&sigset, 1); | 155 | linux.sigaddset(&sigset, 1); |
| 151 | try expectEqual(sigset[0], 1); | 156 | try expectEqual(sigset[0], 1); |
| 152 | try expectEqual(sigset[1], 0); | 157 | if (sigset_len > 1) { |
| 158 | try expectEqual(sigset[1], 0); | ||
| 159 | } | ||
| 153 | 160 | ||
| 154 | linux.sigaddset(&sigset, 31); | 161 | linux.sigaddset(&sigset, 31); |
| 155 | try expectEqual(sigset[0], 0x4000_0001); | 162 | try expectEqual(sigset[0], 0x4000_0001); |
| 156 | try expectEqual(sigset[1], 0); | 163 | if (sigset_len > 1) { |
| 164 | try expectEqual(sigset[1], 0); | ||
| 165 | } | ||
| 157 | 166 | ||
| 158 | linux.sigaddset(&sigset, 36); | 167 | linux.sigaddset(&sigset, 36); |
| 159 | try expectEqual(sigset[0], 0x4000_0001); | 168 | if (sigset_elemis64) { |
| 160 | try expectEqual(sigset[1], 0x8); | 169 | try expectEqual(sigset[0], 0x8_4000_0001); |
| 170 | } else { | ||
| 171 | try expectEqual(sigset[0], 0x4000_0001); | ||
| 172 | try expectEqual(sigset[1], 0x8); | ||
| 173 | } | ||
| 161 | 174 | ||
| 162 | linux.sigaddset(&sigset, 64); | 175 | linux.sigaddset(&sigset, 64); |
| 163 | try expectEqual(sigset[0], 0x4000_0001); | 176 | if (sigset_elemis64) { |
| 164 | try expectEqual(sigset[1], 0x8000_0008); | 177 | try expectEqual(sigset[0], 0x8000_0008_4000_0001); |
| 165 | try expectEqual(sigset[2], 0); | 178 | } else { |
| 179 | try expectEqual(sigset[0], 0x4000_0001); | ||
| 180 | try expectEqual(sigset[1], 0x8000_0008); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | test "sigfillset" { | ||
| 185 | // unlike the C library, all the signals are set in the kernel-level fillset | ||
| 186 | const sigset = linux.sigfillset(); | ||
| 187 | for (1..linux.NSIG) |i| { | ||
| 188 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), true); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | test "sigemptyset" { | ||
| 193 | const sigset = linux.sigemptyset(); | ||
| 194 | for (1..linux.NSIG) |i| { | ||
| 195 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), false); | ||
| 196 | } | ||
| 166 | } | 197 | } |
| 167 | 198 | ||
| 168 | test "sysinfo" { | 199 | test "sysinfo" { |
lib/std/os/linux/x86.zig+1-1| ... | @@ -350,7 +350,7 @@ pub const ucontext_t = extern struct { | ... | @@ -350,7 +350,7 @@ pub const ucontext_t = extern struct { |
| 350 | link: ?*ucontext_t, | 350 | link: ?*ucontext_t, |
| 351 | stack: stack_t, | 351 | stack: stack_t, |
| 352 | mcontext: mcontext_t, | 352 | mcontext: mcontext_t, |
| 353 | sigmask: sigset_t, | 353 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask |
| 354 | regspace: [64]u64, | 354 | regspace: [64]u64, |
| 355 | }; | 355 | }; |
| 356 | 356 |
lib/std/os/linux/x86_64.zig+11-3| ... | @@ -369,13 +369,21 @@ pub const mcontext_t = extern struct { | ... | @@ -369,13 +369,21 @@ pub const mcontext_t = extern struct { |
| 369 | reserved1: [8]usize = undefined, | 369 | reserved1: [8]usize = undefined, |
| 370 | }; | 370 | }; |
| 371 | 371 | ||
| 372 | /// ucontext_t is part of the state pushed on the stack by the kernel for | ||
| 373 | /// a signal handler. And also a subset of the state returned from the | ||
| 374 | /// makecontext/getcontext/swapcontext POSIX APIs. | ||
| 375 | /// | ||
| 376 | /// Currently this structure matches the glibc/musl layout. It contains a | ||
| 377 | /// 1024-bit signal mask, and `fpregs_mem`. This structure should be | ||
| 378 | /// split into one for the kernel ABI and c.zig should define a glibc/musl | ||
| 379 | /// compatible structure. | ||
| 372 | pub const ucontext_t = extern struct { | 380 | pub const ucontext_t = extern struct { |
| 373 | flags: usize, | 381 | flags: usize, |
| 374 | link: ?*ucontext_t, | 382 | link: ?*ucontext_t, |
| 375 | stack: stack_t, | 383 | stack: stack_t, |
| 376 | mcontext: mcontext_t, | 384 | mcontext: mcontext_t, |
| 377 | sigmask: sigset_t, | 385 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a glibc-compatible (1024-bit) sigmask. |
| 378 | fpregs_mem: [64]usize, | 386 | fpregs_mem: [64]usize, // Not part of kernel ABI, only part of glibc ucontext_t |
| 379 | }; | 387 | }; |
| 380 | 388 | ||
| 381 | fn gpRegisterOffset(comptime reg_index: comptime_int) usize { | 389 | fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| ... | @@ -455,7 +463,7 @@ fn getContextInternal() callconv(.naked) usize { | ... | @@ -455,7 +463,7 @@ fn getContextInternal() callconv(.naked) usize { |
| 455 | [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), | 463 | [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), |
| 456 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), | 464 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), |
| 457 | [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), | 465 | [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), |
| 458 | [sigset_size] "i" (linux.NSIG / 8), | 466 | [sigset_size] "i" (@sizeOf(sigset_t)), |
| 459 | : "cc", "memory", "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" | 467 | : "cc", "memory", "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" |
| 460 | ); | 468 | ); |
| 461 | } | 469 | } |
lib/std/os/plan9.zig+4-1| ... | @@ -182,7 +182,6 @@ pub const SIG = struct { | ... | @@ -182,7 +182,6 @@ pub const SIG = struct { |
| 182 | pub const TTOU = 20; | 182 | pub const TTOU = 20; |
| 183 | }; | 183 | }; |
| 184 | pub const sigset_t = c_long; | 184 | pub const sigset_t = c_long; |
| 185 | pub const empty_sigset = 0; | ||
| 186 | pub const siginfo_t = c_long; | 185 | pub const siginfo_t = c_long; |
| 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we include it here to be compatible. | 186 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we include it here to be compatible. |
| 188 | pub const Sigaction = extern struct { | 187 | pub const Sigaction = extern struct { |
| ... | @@ -199,6 +198,10 @@ pub const Sigaction = extern struct { | ... | @@ -199,6 +198,10 @@ pub const Sigaction = extern struct { |
| 199 | pub const AT = struct { | 198 | pub const AT = struct { |
| 200 | pub const FDCWD = -100; // we just make up a constant; FDCWD and openat don't actually exist in plan9 | 199 | pub const FDCWD = -100; // we just make up a constant; FDCWD and openat don't actually exist in plan9 |
| 201 | }; | 200 | }; |
| 201 | // Plan 9 doesn't do signals. This is just needed to get through start.zig. | ||
| 202 | pub fn sigemptyset() sigset_t { | ||
| 203 | return 0; | ||
| 204 | } | ||
| 202 | // TODO implement sigaction | 205 | // TODO implement sigaction |
| 203 | // right now it is just a shim to allow using start.zig code | 206 | // right now it is just a shim to allow using start.zig code |
| 204 | pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { | 207 | pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { |
lib/std/posix.zig+69-18| ... | @@ -86,6 +86,7 @@ pub const MREMAP = system.MREMAP; | ... | @@ -86,6 +86,7 @@ pub const MREMAP = system.MREMAP; |
| 86 | pub const MSF = system.MSF; | 86 | pub const MSF = system.MSF; |
| 87 | pub const MSG = system.MSG; | 87 | pub const MSG = system.MSG; |
| 88 | pub const NAME_MAX = system.NAME_MAX; | 88 | pub const NAME_MAX = system.NAME_MAX; |
| 89 | pub const NSIG = system.NSIG; | ||
| 89 | pub const O = system.O; | 90 | pub const O = system.O; |
| 90 | pub const PATH_MAX = system.PATH_MAX; | 91 | pub const PATH_MAX = system.PATH_MAX; |
| 91 | pub const POLL = system.POLL; | 92 | pub const POLL = system.POLL; |
| ... | @@ -126,10 +127,8 @@ pub const timerfd_clockid_t = system.timerfd_clockid_t; | ... | @@ -126,10 +127,8 @@ pub const timerfd_clockid_t = system.timerfd_clockid_t; |
| 126 | pub const cpu_set_t = system.cpu_set_t; | 127 | pub const cpu_set_t = system.cpu_set_t; |
| 127 | pub const dev_t = system.dev_t; | 128 | pub const dev_t = system.dev_t; |
| 128 | pub const dl_phdr_info = system.dl_phdr_info; | 129 | pub const dl_phdr_info = system.dl_phdr_info; |
| 129 | pub const empty_sigset = system.empty_sigset; | ||
| 130 | pub const fd_t = system.fd_t; | 130 | pub const fd_t = system.fd_t; |
| 131 | pub const file_obj = system.file_obj; | 131 | pub const file_obj = system.file_obj; |
| 132 | pub const filled_sigset = system.filled_sigset; | ||
| 133 | pub const gid_t = system.gid_t; | 132 | pub const gid_t = system.gid_t; |
| 134 | pub const ifreq = system.ifreq; | 133 | pub const ifreq = system.ifreq; |
| 135 | pub const ino_t = system.ino_t; | 134 | pub const ino_t = system.ino_t; |
| ... | @@ -678,7 +677,8 @@ pub fn abort() noreturn { | ... | @@ -678,7 +677,8 @@ pub fn abort() noreturn { |
| 678 | raise(SIG.ABRT) catch {}; | 677 | raise(SIG.ABRT) catch {}; |
| 679 | 678 | ||
| 680 | // Disable all signal handlers. | 679 | // Disable all signal handlers. |
| 681 | sigprocmask(SIG.BLOCK, &linux.all_mask, null); | 680 | const filledset = linux.sigfillset(); |
| 681 | sigprocmask(SIG.BLOCK, &filledset, null); | ||
| 682 | 682 | ||
| 683 | // Only one thread may proceed to the rest of abort(). | 683 | // Only one thread may proceed to the rest of abort(). |
| 684 | if (!builtin.single_threaded) { | 684 | if (!builtin.single_threaded) { |
| ... | @@ -691,14 +691,15 @@ pub fn abort() noreturn { | ... | @@ -691,14 +691,15 @@ pub fn abort() noreturn { |
| 691 | // Install default handler so that the tkill below will terminate. | 691 | // Install default handler so that the tkill below will terminate. |
| 692 | const sigact = Sigaction{ | 692 | const sigact = Sigaction{ |
| 693 | .handler = .{ .handler = SIG.DFL }, | 693 | .handler = .{ .handler = SIG.DFL }, |
| 694 | .mask = empty_sigset, | 694 | .mask = sigemptyset(), |
| 695 | .flags = 0, | 695 | .flags = 0, |
| 696 | }; | 696 | }; |
| 697 | sigaction(SIG.ABRT, &sigact, null); | 697 | sigaction(SIG.ABRT, &sigact, null); |
| 698 | 698 | ||
| 699 | _ = linux.tkill(linux.gettid(), SIG.ABRT); | 699 | _ = linux.tkill(linux.gettid(), SIG.ABRT); |
| 700 | 700 | ||
| 701 | const sigabrtmask: linux.sigset_t = [_]u32{0} ** 31 ++ [_]u32{1 << (SIG.ABRT - 1)}; | 701 | var sigabrtmask = sigemptyset(); |
| 702 | sigaddset(&sigabrtmask, SIG.ABRT); | ||
| 702 | sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); | 703 | sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); |
| 703 | 704 | ||
| 704 | // Beyond this point should be unreachable. | 705 | // Beyond this point should be unreachable. |
| ... | @@ -723,18 +724,13 @@ pub fn raise(sig: u8) RaiseError!void { | ... | @@ -723,18 +724,13 @@ pub fn raise(sig: u8) RaiseError!void { |
| 723 | } | 724 | } |
| 724 | 725 | ||
| 725 | if (native_os == .linux) { | 726 | if (native_os == .linux) { |
| 726 | // https://git.musl-libc.org/cgit/musl/commit/?id=0bed7e0acfd34e3fb63ca0e4d99b7592571355a9 | 727 | // Block all signals so a `fork` (from a signal handler) between the gettid() and kill() syscalls |
| 727 | // | 728 | // cannot trigger an extra, unexpected, inter-process signal. Signal paranoia inherited from Musl. |
| 728 | // Unlike musl, libc-less Zig std does not have any internal signals for implementation purposes, so we | 729 | const filled = linux.sigfillset(); |
| 729 | // need to block all signals on the assumption that any of them could potentially fork() in a handler. | 730 | var orig: sigset_t = undefined; |
| 730 | var set: sigset_t = undefined; | 731 | sigprocmask(SIG.BLOCK, &filled, &orig); |
| 731 | sigprocmask(SIG.BLOCK, &linux.all_mask, &set); | 732 | const rc = linux.tkill(linux.gettid(), sig); |
| 732 | 733 | sigprocmask(SIG.SETMASK, &orig, null); | |
| 733 | const tid = linux.gettid(); | ||
| 734 | const rc = linux.tkill(tid, sig); | ||
| 735 | |||
| 736 | // restore signal mask | ||
| 737 | sigprocmask(SIG.SETMASK, &set, null); | ||
| 738 | 734 | ||
| 739 | switch (errno(rc)) { | 735 | switch (errno(rc)) { |
| 740 | .SUCCESS => return, | 736 | .SUCCESS => return, |
| ... | @@ -5818,8 +5814,63 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { | ... | @@ -5818,8 +5814,63 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { |
| 5818 | } | 5814 | } |
| 5819 | } | 5815 | } |
| 5820 | 5816 | ||
| 5817 | /// Return a filled sigset_t. | ||
| 5818 | pub fn sigfillset() sigset_t { | ||
| 5819 | if (builtin.link_libc) { | ||
| 5820 | var set: sigset_t = undefined; | ||
| 5821 | switch (errno(system.sigfillset(&set))) { | ||
| 5822 | .SUCCESS => return set, | ||
| 5823 | else => unreachable, | ||
| 5824 | } | ||
| 5825 | } | ||
| 5826 | return system.sigfillset(); | ||
| 5827 | } | ||
| 5828 | |||
| 5829 | /// Return an empty sigset_t. | ||
| 5830 | pub fn sigemptyset() sigset_t { | ||
| 5831 | if (builtin.link_libc) { | ||
| 5832 | var set: sigset_t = undefined; | ||
| 5833 | switch (errno(system.sigemptyset(&set))) { | ||
| 5834 | .SUCCESS => return set, | ||
| 5835 | else => unreachable, | ||
| 5836 | } | ||
| 5837 | } | ||
| 5838 | return system.sigemptyset(); | ||
| 5839 | } | ||
| 5840 | |||
| 5841 | pub fn sigaddset(set: *sigset_t, sig: u8) void { | ||
| 5842 | if (builtin.link_libc) { | ||
| 5843 | switch (errno(system.sigaddset(set, sig))) { | ||
| 5844 | .SUCCESS => return, | ||
| 5845 | else => unreachable, | ||
| 5846 | } | ||
| 5847 | } | ||
| 5848 | system.sigaddset(set, sig); | ||
| 5849 | } | ||
| 5850 | |||
| 5851 | pub fn sigdelset(set: *sigset_t, sig: u8) void { | ||
| 5852 | if (builtin.link_libc) { | ||
| 5853 | switch (errno(system.sigdelset(set, sig))) { | ||
| 5854 | .SUCCESS => return, | ||
| 5855 | else => unreachable, | ||
| 5856 | } | ||
| 5857 | } | ||
| 5858 | system.sigdelset(set, sig); | ||
| 5859 | } | ||
| 5860 | |||
| 5861 | pub fn sigismember(set: *const sigset_t, sig: u8) bool { | ||
| 5862 | if (builtin.link_libc) { | ||
| 5863 | const rc = system.sigismember(set, sig); | ||
| 5864 | switch (errno(rc)) { | ||
| 5865 | .SUCCESS => return rc == 1, | ||
| 5866 | else => unreachable, | ||
| 5867 | } | ||
| 5868 | } | ||
| 5869 | return system.sigismember(set, sig); | ||
| 5870 | } | ||
| 5871 | |||
| 5821 | /// Examine and change a signal action. | 5872 | /// Examine and change a signal action. |
| 5822 | pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) void { | 5873 | pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) void { |
| 5823 | switch (errno(system.sigaction(sig, act, oact))) { | 5874 | switch (errno(system.sigaction(sig, act, oact))) { |
| 5824 | .SUCCESS => return, | 5875 | .SUCCESS => return, |
| 5825 | // EINVAL means the signal is either invalid or some signal that cannot have its action | 5876 | // EINVAL means the signal is either invalid or some signal that cannot have its action |
lib/std/posix/test.zig+147-26| ... | @@ -859,12 +859,61 @@ test "shutdown socket" { | ... | @@ -859,12 +859,61 @@ test "shutdown socket" { |
| 859 | std.net.Stream.close(.{ .handle = sock }); | 859 | std.net.Stream.close(.{ .handle = sock }); |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | test "sigaction" { | 862 | test "sigset empty/full" { |
| 863 | if (native_os == .wasi or native_os == .windows) | ||
| 864 | return error.SkipZigTest; | ||
| 865 | |||
| 866 | var set: posix.sigset_t = posix.sigemptyset(); | ||
| 867 | for (1..posix.NSIG) |i| { | ||
| 868 | try expectEqual(false, posix.sigismember(&set, @truncate(i))); | ||
| 869 | } | ||
| 870 | |||
| 871 | // The C library can reserve some (unnamed) signals, so can't check the full | ||
| 872 | // NSIG set is defined, but just test a couple: | ||
| 873 | set = posix.sigfillset(); | ||
| 874 | try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.CHLD))); | ||
| 875 | try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT))); | ||
| 876 | } | ||
| 877 | |||
| 878 | // Some signals (32 - 34 on glibc/musl) are not allowed to be added to a | ||
| 879 | // sigset by the C library, so avoid testing them. | ||
| 880 | fn reserved_signo(i: usize) bool { | ||
| 881 | return builtin.link_libc and (i >= 32 and i <= 34); | ||
| 882 | } | ||
| 883 | |||
| 884 | test "sigset add/del" { | ||
| 863 | if (native_os == .wasi or native_os == .windows) | 885 | if (native_os == .wasi or native_os == .windows) |
| 864 | return error.SkipZigTest; | 886 | return error.SkipZigTest; |
| 865 | 887 | ||
| 866 | // https://github.com/ziglang/zig/issues/7427 | 888 | var sigset: posix.sigset_t = posix.sigemptyset(); |
| 867 | if (native_os == .linux and builtin.target.cpu.arch == .x86) | 889 | |
| 890 | // See that none are set, then set each one, see that they're all set, then | ||
| 891 | // remove them all, and then see that none are set. | ||
| 892 | for (1..posix.NSIG) |i| { | ||
| 893 | try expectEqual(false, posix.sigismember(&sigset, @truncate(i))); | ||
| 894 | } | ||
| 895 | for (1..posix.NSIG) |i| { | ||
| 896 | if (!reserved_signo(i)) { | ||
| 897 | posix.sigaddset(&sigset, @truncate(i)); | ||
| 898 | } | ||
| 899 | } | ||
| 900 | for (1..posix.NSIG) |i| { | ||
| 901 | if (!reserved_signo(i)) { | ||
| 902 | try expectEqual(true, posix.sigismember(&sigset, @truncate(i))); | ||
| 903 | } | ||
| 904 | } | ||
| 905 | for (1..posix.NSIG) |i| { | ||
| 906 | if (!reserved_signo(i)) { | ||
| 907 | posix.sigdelset(&sigset, @truncate(i)); | ||
| 908 | } | ||
| 909 | } | ||
| 910 | for (1..posix.NSIG) |i| { | ||
| 911 | try expectEqual(false, posix.sigismember(&sigset, @truncate(i))); | ||
| 912 | } | ||
| 913 | } | ||
| 914 | |||
| 915 | test "sigaction" { | ||
| 916 | if (native_os == .wasi or native_os == .windows) | ||
| 868 | return error.SkipZigTest; | 917 | return error.SkipZigTest; |
| 869 | 918 | ||
| 870 | // https://github.com/ziglang/zig/issues/15381 | 919 | // https://github.com/ziglang/zig/issues/15381 |
| ... | @@ -872,66 +921,138 @@ test "sigaction" { | ... | @@ -872,66 +921,138 @@ test "sigaction" { |
| 872 | return error.SkipZigTest; | 921 | return error.SkipZigTest; |
| 873 | } | 922 | } |
| 874 | 923 | ||
| 924 | const test_signo = posix.SIG.URG; // URG only because it is ignored by default in debuggers | ||
| 925 | |||
| 875 | const S = struct { | 926 | const S = struct { |
| 876 | var handler_called_count: u32 = 0; | 927 | var handler_called_count: u32 = 0; |
| 877 | 928 | ||
| 878 | fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void { | 929 | fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void { |
| 879 | _ = ctx_ptr; | 930 | _ = ctx_ptr; |
| 880 | // Check that we received the correct signal. | 931 | // Check that we received the correct signal. |
| 881 | switch (native_os) { | 932 | const info_sig = switch (native_os) { |
| 882 | .netbsd => { | 933 | .netbsd => info.info.signo, |
| 883 | if (sig == posix.SIG.USR1 and sig == info.info.signo) | 934 | else => info.signo, |
| 884 | handler_called_count += 1; | 935 | }; |
| 885 | }, | 936 | if (sig == test_signo and sig == info_sig) { |
| 886 | else => { | 937 | handler_called_count += 1; |
| 887 | if (sig == posix.SIG.USR1 and sig == info.signo) | ||
| 888 | handler_called_count += 1; | ||
| 889 | }, | ||
| 890 | } | 938 | } |
| 891 | } | 939 | } |
| 892 | }; | 940 | }; |
| 893 | 941 | ||
| 894 | var sa: posix.Sigaction = .{ | 942 | var sa: posix.Sigaction = .{ |
| 895 | .handler = .{ .sigaction = &S.handler }, | 943 | .handler = .{ .sigaction = &S.handler }, |
| 896 | .mask = posix.empty_sigset, | 944 | .mask = posix.sigemptyset(), |
| 897 | .flags = posix.SA.SIGINFO | posix.SA.RESETHAND, | 945 | .flags = posix.SA.SIGINFO | posix.SA.RESETHAND, |
| 898 | }; | 946 | }; |
| 947 | |||
| 899 | var old_sa: posix.Sigaction = undefined; | 948 | var old_sa: posix.Sigaction = undefined; |
| 900 | 949 | ||
| 901 | // Install the new signal handler. | 950 | // Install the new signal handler. |
| 902 | posix.sigaction(posix.SIG.USR1, &sa, null); | 951 | posix.sigaction(test_signo, &sa, null); |
| 903 | 952 | ||
| 904 | // Check that we can read it back correctly. | 953 | // Check that we can read it back correctly. |
| 905 | posix.sigaction(posix.SIG.USR1, null, &old_sa); | 954 | posix.sigaction(test_signo, null, &old_sa); |
| 906 | try testing.expectEqual(&S.handler, old_sa.handler.sigaction.?); | 955 | try testing.expectEqual(&S.handler, old_sa.handler.sigaction.?); |
| 907 | try testing.expect((old_sa.flags & posix.SA.SIGINFO) != 0); | 956 | try testing.expect((old_sa.flags & posix.SA.SIGINFO) != 0); |
| 908 | 957 | ||
| 909 | // Invoke the handler. | 958 | // Invoke the handler. |
| 910 | try posix.raise(posix.SIG.USR1); | 959 | try posix.raise(test_signo); |
| 911 | try testing.expect(S.handler_called_count == 1); | 960 | try testing.expectEqual(1, S.handler_called_count); |
| 912 | 961 | ||
| 913 | // Check if passing RESETHAND correctly reset the handler to SIG_DFL | 962 | // Check if passing RESETHAND correctly reset the handler to SIG_DFL |
| 914 | posix.sigaction(posix.SIG.USR1, null, &old_sa); | 963 | posix.sigaction(test_signo, null, &old_sa); |
| 915 | try testing.expectEqual(posix.SIG.DFL, old_sa.handler.handler); | 964 | try testing.expectEqual(posix.SIG.DFL, old_sa.handler.handler); |
| 916 | 965 | ||
| 917 | // Reinstall the signal w/o RESETHAND and re-raise | 966 | // Reinstall the signal w/o RESETHAND and re-raise |
| 918 | sa.flags = posix.SA.SIGINFO; | 967 | sa.flags = posix.SA.SIGINFO; |
| 919 | posix.sigaction(posix.SIG.USR1, &sa, null); | 968 | posix.sigaction(test_signo, &sa, null); |
| 920 | try posix.raise(posix.SIG.USR1); | 969 | try posix.raise(test_signo); |
| 921 | try testing.expect(S.handler_called_count == 2); | 970 | try testing.expectEqual(2, S.handler_called_count); |
| 922 | 971 | ||
| 923 | // Now set the signal to ignored | 972 | // Now set the signal to ignored |
| 924 | sa.handler = .{ .handler = posix.SIG.IGN }; | 973 | sa.handler = .{ .handler = posix.SIG.IGN }; |
| 925 | sa.flags = 0; | 974 | sa.flags = 0; |
| 926 | posix.sigaction(posix.SIG.USR1, &sa, null); | 975 | posix.sigaction(test_signo, &sa, null); |
| 927 | 976 | ||
| 928 | // Re-raise to ensure handler is actually ignored | 977 | // Re-raise to ensure handler is actually ignored |
| 929 | try posix.raise(posix.SIG.USR1); | 978 | try posix.raise(test_signo); |
| 930 | try testing.expect(S.handler_called_count == 2); | 979 | try testing.expectEqual(2, S.handler_called_count); |
| 931 | 980 | ||
| 932 | // Ensure that ignored state is returned when querying | 981 | // Ensure that ignored state is returned when querying |
| 933 | posix.sigaction(posix.SIG.USR1, null, &old_sa); | 982 | posix.sigaction(test_signo, null, &old_sa); |
| 934 | try testing.expectEqual(posix.SIG.IGN, old_sa.handler.handler.?); | 983 | try testing.expectEqual(posix.SIG.IGN, old_sa.handler.handler); |
| 984 | } | ||
| 985 | |||
| 986 | test "sigset_t bits" { | ||
| 987 | if (native_os == .wasi or native_os == .windows) | ||
| 988 | return error.SkipZigTest; | ||
| 989 | |||
| 990 | const S = struct { | ||
| 991 | var expected_sig: i32 = undefined; | ||
| 992 | var handler_called_count: u32 = 0; | ||
| 993 | |||
| 994 | fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void { | ||
| 995 | _ = ctx_ptr; | ||
| 996 | |||
| 997 | const info_sig = switch (native_os) { | ||
| 998 | .netbsd => info.info.signo, | ||
| 999 | else => info.signo, | ||
| 1000 | }; | ||
| 1001 | if (sig == expected_sig and sig == info_sig) { | ||
| 1002 | handler_called_count += 1; | ||
| 1003 | } | ||
| 1004 | } | ||
| 1005 | }; | ||
| 1006 | |||
| 1007 | const self_pid = posix.system.getpid(); | ||
| 1008 | |||
| 1009 | // To check that sigset_t mapping matches kernel (think u32/u64 mismatches on | ||
| 1010 | // big-endian), try sending a blocked signal to make sure the mask matches the | ||
| 1011 | // signal. (Send URG and CHLD because they're ignored by default in the | ||
| 1012 | // debugger, vs. USR1 or other named signals) | ||
| 1013 | inline for ([_]usize{ posix.SIG.URG, posix.SIG.CHLD, 62, 94, 126 }) |test_signo| { | ||
| 1014 | if (test_signo >= posix.NSIG) continue; | ||
| 1015 | |||
| 1016 | S.expected_sig = test_signo; | ||
| 1017 | S.handler_called_count = 0; | ||
| 1018 | |||
| 1019 | const sa: posix.Sigaction = .{ | ||
| 1020 | .handler = .{ .sigaction = &S.handler }, | ||
| 1021 | .mask = posix.sigemptyset(), | ||
| 1022 | .flags = posix.SA.SIGINFO | posix.SA.RESETHAND, | ||
| 1023 | }; | ||
| 1024 | |||
| 1025 | var old_sa: posix.Sigaction = undefined; | ||
| 1026 | |||
| 1027 | // Install the new signal handler. | ||
| 1028 | posix.sigaction(test_signo, &sa, &old_sa); | ||
| 1029 | |||
| 1030 | // block the signal and see that its delayed until unblocked | ||
| 1031 | var block_one: posix.sigset_t = posix.sigemptyset(); | ||
| 1032 | posix.sigaddset(&block_one, test_signo); | ||
| 1033 | posix.sigprocmask(posix.SIG.BLOCK, &block_one, null); | ||
| 1034 | |||
| 1035 | // qemu maps target signals to host signals 1-to-1, so targets | ||
| 1036 | // with more signals than the host will fail to send the signal. | ||
| 1037 | const rc = posix.system.kill(self_pid, test_signo); | ||
| 1038 | switch (posix.errno(rc)) { | ||
| 1039 | .SUCCESS => { | ||
| 1040 | // See that the signal is blocked, then unblocked | ||
| 1041 | try testing.expectEqual(0, S.handler_called_count); | ||
| 1042 | posix.sigprocmask(posix.SIG.UNBLOCK, &block_one, null); | ||
| 1043 | try testing.expectEqual(1, S.handler_called_count); | ||
| 1044 | }, | ||
| 1045 | .INVAL => { | ||
| 1046 | // Signal won't get delviered. Just clean up. | ||
| 1047 | posix.sigprocmask(posix.SIG.UNBLOCK, &block_one, null); | ||
| 1048 | try testing.expectEqual(0, S.handler_called_count); | ||
| 1049 | }, | ||
| 1050 | else => |errno| return posix.unexpectedErrno(errno), | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | // Restore original handler | ||
| 1054 | posix.sigaction(test_signo, &old_sa, null); | ||
| 1055 | } | ||
| 935 | } | 1056 | } |
| 936 | 1057 | ||
| 937 | test "dup & dup2" { | 1058 | test "dup & dup2" { |
lib/std/start.zig+1-1| ... | @@ -749,7 +749,7 @@ fn maybeIgnoreSigpipe() void { | ... | @@ -749,7 +749,7 @@ fn maybeIgnoreSigpipe() void { |
| 749 | // Set handler to a noop function instead of `SIG.IGN` to prevent | 749 | // Set handler to a noop function instead of `SIG.IGN` to prevent |
| 750 | // leaking signal disposition to a child process. | 750 | // leaking signal disposition to a child process. |
| 751 | .handler = .{ .handler = noopSigHandler }, | 751 | .handler = .{ .handler = noopSigHandler }, |
| 752 | .mask = posix.empty_sigset, | 752 | .mask = posix.sigemptyset(), |
| 753 | .flags = 0, | 753 | .flags = 0, |
| 754 | }; | 754 | }; |
| 755 | posix.sigaction(posix.SIG.PIPE, &act, null); | 755 | posix.sigaction(posix.SIG.PIPE, &act, null); |
src/crash_report.zig+2-3| ... | @@ -175,12 +175,11 @@ pub fn attachSegfaultHandler() void { | ... | @@ -175,12 +175,11 @@ pub fn attachSegfaultHandler() void { |
| 175 | _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); | 175 | _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); |
| 176 | return; | 176 | return; |
| 177 | } | 177 | } |
| 178 | var act: posix.Sigaction = .{ | 178 | const act: posix.Sigaction = .{ |
| 179 | .handler = .{ .sigaction = handleSegfaultPosix }, | 179 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 180 | .mask = posix.empty_sigset, | 180 | .mask = posix.sigemptyset(), |
| 181 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), | 181 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), |
| 182 | }; | 182 | }; |
| 183 | |||
| 184 | debug.updateSegfaultHandler(&act); | 183 | debug.updateSegfaultHandler(&act); |
| 185 | } | 184 | } |
| 186 | 185 |
test/standalone/sigpipe/build.zig+1-1| ... | @@ -18,7 +18,7 @@ pub fn build(b: *std.build.Builder) !void { | ... | @@ -18,7 +18,7 @@ pub fn build(b: *std.build.Builder) !void { |
| 18 | { | 18 | { |
| 19 | const act = posix.Sigaction{ | 19 | const act = posix.Sigaction{ |
| 20 | .handler = .{ .handler = posix.SIG.DFL }, | 20 | .handler = .{ .handler = posix.SIG.DFL }, |
| 21 | .mask = posix.empty_sigset, | 21 | .mask = posix.sigemptyset(), |
| 22 | .flags = 0, | 22 | .flags = 0, |
| 23 | }; | 23 | }; |
| 24 | try posix.sigaction(posix.SIG.PIPE, &act, null); | 24 | try posix.sigaction(posix.SIG.PIPE, &act, null); |