| 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 | 410 | } |
| 411 | 411 | |
| 412 | 412 | if (have_sigwinch) { |
| 413 | var act: posix.Sigaction = .{ | |
| 413 | const act: posix.Sigaction = .{ | |
| 414 | 414 | .handler = .{ .sigaction = handleSigWinch }, |
| 415 | .mask = posix.empty_sigset, | |
| 415 | .mask = posix.sigemptyset(), | |
| 416 | 416 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART), |
| 417 | 417 | }; |
| 418 | 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 | 3115 | .linux => linux.SYS, |
| 3116 | 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 | 3133 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 3119 | 3134 | pub const Sigaction = switch (native_os) { |
| 3120 | 3135 | .linux => switch (native_arch) { |
| ... | ... | @@ -3123,7 +3138,7 @@ pub const Sigaction = switch (native_os) { |
| 3123 | 3138 | .mips64, |
| 3124 | 3139 | .mips64el, |
| 3125 | 3140 | => if (builtin.target.abi.isMusl()) |
| 3126 | linux.Sigaction | |
| 3141 | common_linux_Sigaction | |
| 3127 | 3142 | else if (builtin.target.ptrBitWidth() == 64) extern struct { |
| 3128 | 3143 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; |
| 3129 | 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 | 3175 | flags: c_uint, |
| 3161 | 3176 | restorer: ?*const fn () callconv(.c) void = null, |
| 3162 | 3177 | mask: sigset_t, |
| 3163 | } else linux.Sigaction, | |
| 3164 | else => linux.Sigaction, | |
| 3178 | } else common_linux_Sigaction, | |
| 3179 | else => common_linux_Sigaction, | |
| 3165 | 3180 | }, |
| 3166 | 3181 | .emscripten => emscripten.Sigaction, |
| 3167 | 3182 | .netbsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct { |
| ... | ... | @@ -4518,27 +4533,18 @@ pub const siginfo_t = switch (native_os) { |
| 4518 | 4533 | else => void, |
| 4519 | 4534 | }; |
| 4520 | 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 | 4537 | .emscripten => emscripten.sigset_t, |
| 4523 | 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 | 4541 | .dragonfly, .netbsd, .solaris, .illumos, .freebsd => extern struct { |
| 4526 | 4542 | __bits: [SIG.WORDS]u32, |
| 4527 | 4543 | }, |
| 4528 | 4544 | .haiku => u64, |
| 4529 | 4545 | else => u0, |
| 4530 | 4546 | }; |
| 4531 | pub const empty_sigset: sigset_t = switch (native_os) { | |
| 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 | }; | |
| 4547 | ||
| 4542 | 4548 | pub const sigval = switch (native_os) { |
| 4543 | 4549 | .linux => linux.sigval, |
| 4544 | 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 | 6671 | }; |
| 6666 | 6672 | |
| 6667 | 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 | 6675 | .emscripten => emscripten.ucontext_t, |
| 6670 | 6676 | .macos, .ios, .tvos, .watchos, .visionos => extern struct { |
| 6671 | 6677 | onstack: c_int, |
| ... | ... | @@ -9596,6 +9602,7 @@ pub const NSIG = switch (native_os) { |
| 9596 | 9602 | .windows => 23, |
| 9597 | 9603 | .haiku => 65, |
| 9598 | 9604 | .netbsd, .freebsd => 32, |
| 9605 | .macos => darwin.NSIG, | |
| 9599 | 9606 | .solaris, .illumos => 75, |
| 9600 | 9607 | // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 |
| 9601 | 9608 | .openbsd, .serenity => 33, |
| ... | ... | @@ -10345,6 +10352,11 @@ pub const sigfillset = switch (native_os) { |
| 10345 | 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 | 10360 | pub const sigprocmask = switch (native_os) { |
| 10349 | 10361 | .netbsd => private.__sigprocmask14, |
| 10350 | 10362 | else => private.sigprocmask, |
| ... | ... | @@ -11025,7 +11037,6 @@ pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np; |
| 11025 | 11037 | pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np; |
| 11026 | 11038 | pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np; |
| 11027 | 11039 | pub const ptrace = darwin.ptrace; |
| 11028 | pub const sigaddset = darwin.sigaddset; | |
| 11029 | 11040 | pub const task_for_pid = darwin.task_for_pid; |
| 11030 | 11041 | pub const task_get_exception_ports = darwin.task_get_exception_ports; |
| 11031 | 11042 | pub const task_info = darwin.task_info; |
| ... | ... | @@ -11148,7 +11159,11 @@ const private = struct { |
| 11148 | 11159 | extern "c" fn sched_yield() c_int; |
| 11149 | 11160 | extern "c" fn sendfile(out_fd: fd_t, in_fd: fd_t, offset: ?*off_t, count: usize) isize; |
| 11150 | 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 | 11167 | extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 11153 | 11168 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 11154 | 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 | 10 | const off_t = std.c.off_t; |
| 11 | 11 | const pid_t = std.c.pid_t; |
| 12 | 12 | const pthread_attr_t = std.c.pthread_attr_t; |
| 13 | const sigset_t = std.c.sigset_t; | |
| 14 | 13 | const timespec = std.c.timespec; |
| 15 | 14 | const sf_hdtr = std.c.sf_hdtr; |
| 16 | 15 | |
| ... | ... | @@ -840,9 +839,11 @@ pub extern "c" fn sendfile( |
| 840 | 839 | flags: u32, |
| 841 | 840 | ) c_int; |
| 842 | 841 | |
| 843 | pub fn sigaddset(set: *sigset_t, signo: u5) void { | |
| 844 | set.* |= @as(u32, 1) << (signo - 1); | |
| 845 | } | |
| 842 | // https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74 | |
| 843 | pub const sigset_t = u32; | |
| 844 | ||
| 845 | // https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/signal.h#L76 | |
| 846 | pub const NSIG = 32; | |
| 846 | 847 | |
| 847 | 848 | pub const qos_class_t = enum(c_uint) { |
| 848 | 849 | /// highest priority QOS class for critical tasks |
lib/std/debug.zig+4-5| ... | ... | @@ -1387,12 +1387,11 @@ pub fn attachSegfaultHandler() void { |
| 1387 | 1387 | windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); |
| 1388 | 1388 | return; |
| 1389 | 1389 | } |
| 1390 | var act = posix.Sigaction{ | |
| 1390 | const act = posix.Sigaction{ | |
| 1391 | 1391 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 1392 | .mask = posix.empty_sigset, | |
| 1392 | .mask = posix.sigemptyset(), | |
| 1393 | 1393 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), |
| 1394 | 1394 | }; |
| 1395 | ||
| 1396 | 1395 | updateSegfaultHandler(&act); |
| 1397 | 1396 | } |
| 1398 | 1397 | |
| ... | ... | @@ -1404,9 +1403,9 @@ fn resetSegfaultHandler() void { |
| 1404 | 1403 | } |
| 1405 | 1404 | return; |
| 1406 | 1405 | } |
| 1407 | var act = posix.Sigaction{ | |
| 1406 | const act = posix.Sigaction{ | |
| 1408 | 1407 | .handler = .{ .handler = posix.SIG.DFL }, |
| 1409 | .mask = posix.empty_sigset, | |
| 1408 | .mask = posix.sigemptyset(), | |
| 1410 | 1409 | .flags = 0, |
| 1411 | 1410 | }; |
| 1412 | 1411 | updateSegfaultHandler(&act); |
lib/std/os/emscripten.zig+3-1| ... | ... | @@ -560,7 +560,9 @@ pub const Sigaction = extern struct { |
| 560 | 560 | }; |
| 561 | 561 | |
| 562 | 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 | 566 | pub const siginfo_t = extern struct { |
| 565 | 567 | signo: i32, |
| 566 | 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 | 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 { | |
| 1749 | assert(sig >= 1); | |
| 1748 | pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { | |
| 1749 | assert(sig > 0); | |
| 1750 | assert(sig < NSIG); | |
| 1750 | 1751 | assert(sig != SIG.KILL); |
| 1751 | 1752 | assert(sig != SIG.STOP); |
| 1752 | 1753 | |
| ... | ... | @@ -1755,14 +1756,15 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 1755 | 1756 | const mask_size = @sizeOf(@TypeOf(ksa.mask)); |
| 1756 | 1757 | |
| 1757 | 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 | 1761 | const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore; |
| 1759 | 1762 | ksa = k_sigaction{ |
| 1760 | 1763 | .handler = new.handler.handler, |
| 1761 | 1764 | .flags = new.flags | SA.RESTORER, |
| 1762 | .mask = undefined, | |
| 1765 | .mask = new.mask, | |
| 1763 | 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 | 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 | 1779 | |
| 1778 | 1780 | if (oact) |old| { |
| 1779 | 1781 | old.handler.handler = oldksa.handler; |
| 1780 | old.flags = @as(c_uint, @truncate(oldksa.flags)); | |
| 1781 | @memcpy(@as([*]u8, @ptrCast(&old.mask))[0..mask_size], @as([*]const u8, @ptrCast(&oldksa.mask))); | |
| 1782 | old.flags = oldksa.flags; | |
| 1783 | old.mask = oldksa.mask; | |
| 1782 | 1784 | } |
| 1783 | 1785 | |
| 1784 | 1786 | return 0; |
| ... | ... | @@ -1786,25 +1788,35 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 1786 | 1788 | |
| 1787 | 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. | |
| 1794 | pub const empty_sigset: sigset_t = [_]u32{0} ** sigset_len; | |
| 1799 | const SigsetElement = c_ulong; | |
| 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 | 1814 | assert(sig > 0); |
| 1802 | 1815 | assert(sig < NSIG); |
| 1803 | 1816 | const bit = sig - 1; |
| 1804 | const shift = @as(u5, @truncate(bit % 32)); | |
| 1805 | 1817 | return .{ |
| 1806 | .word = bit / 32, | |
| 1807 | .mask = @as(u32, 1) << shift, | |
| 1818 | .word = bit / @bitSizeOf(SigsetElement), | |
| 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 | 3499 | pub const UNBLOCK = 2; |
| 3488 | 3500 | pub const SETMASK = 3; |
| 3489 | 3501 | |
| 3502 | // https://github.com/torvalds/linux/blob/ca91b9500108d4cf083a635c2e11c884d5dd20ea/arch/mips/include/uapi/asm/signal.h#L25 | |
| 3490 | 3503 | pub const HUP = 1; |
| 3491 | 3504 | pub const INT = 2; |
| 3492 | 3505 | pub const QUIT = 3; |
| ... | ... | @@ -3494,33 +3507,32 @@ pub const SIG = if (is_mips) struct { |
| 3494 | 3507 | pub const TRAP = 5; |
| 3495 | 3508 | pub const ABRT = 6; |
| 3496 | 3509 | pub const IOT = ABRT; |
| 3497 | pub const BUS = 7; | |
| 3510 | pub const EMT = 7; | |
| 3498 | 3511 | pub const FPE = 8; |
| 3499 | 3512 | pub const KILL = 9; |
| 3500 | pub const USR1 = 10; | |
| 3513 | pub const BUS = 10; | |
| 3501 | 3514 | pub const SEGV = 11; |
| 3502 | pub const USR2 = 12; | |
| 3515 | pub const SYS = 12; | |
| 3503 | 3516 | pub const PIPE = 13; |
| 3504 | 3517 | pub const ALRM = 14; |
| 3505 | 3518 | pub const TERM = 15; |
| 3506 | pub const STKFLT = 16; | |
| 3507 | pub const CHLD = 17; | |
| 3508 | pub const CONT = 18; | |
| 3509 | pub const STOP = 19; | |
| 3510 | pub const TSTP = 20; | |
| 3511 | pub const TTIN = 21; | |
| 3512 | pub const TTOU = 22; | |
| 3513 | pub const URG = 23; | |
| 3514 | pub const XCPU = 24; | |
| 3515 | pub const XFSZ = 25; | |
| 3516 | pub const VTALRM = 26; | |
| 3517 | pub const PROF = 27; | |
| 3518 | pub const WINCH = 28; | |
| 3519 | pub const IO = 29; | |
| 3520 | pub const POLL = 29; | |
| 3521 | pub const PWR = 30; | |
| 3522 | pub const SYS = 31; | |
| 3523 | pub const UNUSED = SIG.SYS; | |
| 3519 | pub const USR1 = 16; | |
| 3520 | pub const USR2 = 17; | |
| 3521 | pub const CHLD = 18; | |
| 3522 | pub const PWR = 19; | |
| 3523 | pub const WINCH = 20; | |
| 3524 | pub const URG = 21; | |
| 3525 | pub const IO = 22; | |
| 3526 | pub const POLL = IO; | |
| 3527 | pub const STOP = 23; | |
| 3528 | pub const TSTP = 24; | |
| 3529 | pub const CONT = 25; | |
| 3530 | pub const TTIN = 26; | |
| 3531 | pub const TTOU = 27; | |
| 3532 | pub const VTALRM = 28; | |
| 3533 | pub const PROF = 29; | |
| 3534 | pub const XCPU = 30; | |
| 3535 | pub const XFZ = 31; | |
| 3524 | 3536 | |
| 3525 | 3537 | pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); |
| 3526 | 3538 | pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); |
| ... | ... | @@ -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 | 5494 | const k_sigaction_funcs = struct { |
| 5487 | 5495 | const handler = ?*align(1) const fn (i32) callconv(.c) void; |
| 5488 | 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 | 5500 | pub const k_sigaction = switch (native_arch) { |
| 5492 | .mips, .mipsel => 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 { | |
| 5501 | .mips, .mipsel, .mips64, .mips64el => extern struct { | |
| 5499 | 5502 | flags: c_uint, |
| 5500 | 5503 | handler: k_sigaction_funcs.handler, |
| 5501 | mask: [2]c_ulong, | |
| 5504 | mask: sigset_t, | |
| 5502 | 5505 | restorer: k_sigaction_funcs.restorer, |
| 5503 | 5506 | }, |
| 5504 | 5507 | else => extern struct { |
| 5505 | 5508 | handler: k_sigaction_funcs.handler, |
| 5506 | 5509 | flags: c_ulong, |
| 5507 | 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 | 5519 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 5513 | pub const Sigaction = extern struct { | |
| 5520 | pub const Sigaction = struct { | |
| 5514 | 5521 | pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; |
| 5515 | 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 | 5526 | sigaction: ?sigaction_fn, |
| 5520 | 5527 | }, |
| 5521 | 5528 | mask: sigset_t, |
| 5522 | flags: c_uint, | |
| 5523 | restorer: ?*const fn () callconv(.c) void = null, | |
| 5529 | flags: switch (native_arch) { | |
| 5530 | .mips, .mipsel, .mips64, .mips64el => c_uint, | |
| 5531 | else => c_ulong, | |
| 5532 | }, | |
| 5524 | 5533 | }; |
| 5525 | 5534 | |
| 5526 | 5535 | pub const SFD = struct { |
lib/std/os/linux/aarch64.zig+1-1| ... | ... | @@ -289,7 +289,7 @@ pub const ucontext_t = extern struct { |
| 289 | 289 | flags: usize, |
| 290 | 290 | link: ?*ucontext_t, |
| 291 | 291 | stack: stack_t, |
| 292 | sigmask: sigset_t, | |
| 292 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 293 | 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 | 337 | link: ?*ucontext_t, |
| 338 | 338 | stack: stack_t, |
| 339 | 339 | mcontext: mcontext_t, |
| 340 | sigmask: sigset_t, | |
| 340 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 341 | 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 | 264 | flags: c_ulong, |
| 265 | 265 | link: ?*ucontext_t, |
| 266 | 266 | stack: stack_t, |
| 267 | sigmask: sigset_t, | |
| 268 | _pad: [1024 / 8 - @sizeOf(sigset_t)]u8, | |
| 267 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 269 | 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 | 341 | stack: stack_t, |
| 342 | 342 | pad: [7]i32, |
| 343 | 343 | regs: *mcontext_t, |
| 344 | sigmask: sigset_t, | |
| 344 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 345 | 345 | pad2: [3]i32, |
| 346 | 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 | 337 | flags: u32, |
| 338 | 338 | link: ?*ucontext_t, |
| 339 | 339 | stack: stack_t, |
| 340 | sigmask: sigset_t, | |
| 340 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 341 | 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 | 273 | link: ?*ucontext_t, |
| 274 | 274 | stack: stack_t, |
| 275 | 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 | 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 | 454 | sigmask: u64, |
| 455 | 455 | mcontext: mcontext_t, |
| 456 | 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 | 460 | /// TODO |
lib/std/os/linux/test.zig+40-9| ... | ... | @@ -126,7 +126,9 @@ test "fadvise" { |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 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 | 133 | // See that none are set, then set each one, see that they're all set, then |
| 132 | 134 | // remove them all, and then see that none are set. |
| ... | ... | @@ -138,7 +140,6 @@ test "sigset_t" { |
| 138 | 140 | } |
| 139 | 141 | for (1..linux.NSIG) |i| { |
| 140 | 142 | try expectEqual(linux.sigismember(&sigset, @truncate(i)), true); |
| 141 | try expectEqual(linux.sigismember(&linux.empty_sigset, @truncate(i)), false); | |
| 142 | 143 | } |
| 143 | 144 | for (1..linux.NSIG) |i| { |
| 144 | 145 | linux.sigdelset(&sigset, @truncate(i)); |
| ... | ... | @@ -147,22 +148,52 @@ test "sigset_t" { |
| 147 | 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 | 155 | linux.sigaddset(&sigset, 1); |
| 151 | 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 | 161 | linux.sigaddset(&sigset, 31); |
| 155 | 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 | 167 | linux.sigaddset(&sigset, 36); |
| 159 | try expectEqual(sigset[0], 0x4000_0001); | |
| 160 | try expectEqual(sigset[1], 0x8); | |
| 168 | if (sigset_elemis64) { | |
| 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 | 175 | linux.sigaddset(&sigset, 64); |
| 163 | try expectEqual(sigset[0], 0x4000_0001); | |
| 164 | try expectEqual(sigset[1], 0x8000_0008); | |
| 165 | try expectEqual(sigset[2], 0); | |
| 176 | if (sigset_elemis64) { | |
| 177 | try expectEqual(sigset[0], 0x8000_0008_4000_0001); | |
| 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 | 199 | test "sysinfo" { |
lib/std/os/linux/x86.zig+1-1| ... | ... | @@ -350,7 +350,7 @@ pub const ucontext_t = extern struct { |
| 350 | 350 | link: ?*ucontext_t, |
| 351 | 351 | stack: stack_t, |
| 352 | 352 | mcontext: mcontext_t, |
| 353 | sigmask: sigset_t, | |
| 353 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a libc-compatible (1024-bit) sigmask | |
| 354 | 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 | 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 | 380 | pub const ucontext_t = extern struct { |
| 373 | 381 | flags: usize, |
| 374 | 382 | link: ?*ucontext_t, |
| 375 | 383 | stack: stack_t, |
| 376 | 384 | mcontext: mcontext_t, |
| 377 | sigmask: sigset_t, | |
| 378 | fpregs_mem: [64]usize, | |
| 385 | sigmask: [1024 / @bitSizeOf(c_ulong)]c_ulong, // Currently a glibc-compatible (1024-bit) sigmask. | |
| 386 | fpregs_mem: [64]usize, // Not part of kernel ABI, only part of glibc ucontext_t | |
| 379 | 387 | }; |
| 380 | 388 | |
| 381 | 389 | fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| ... | ... | @@ -455,7 +463,7 @@ fn getContextInternal() callconv(.naked) usize { |
| 455 | 463 | [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), |
| 456 | 464 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), |
| 457 | 465 | [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), |
| 458 | [sigset_size] "i" (linux.NSIG / 8), | |
| 466 | [sigset_size] "i" (@sizeOf(sigset_t)), | |
| 459 | 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 | 182 | pub const TTOU = 20; |
| 183 | 183 | }; |
| 184 | 184 | pub const sigset_t = c_long; |
| 185 | pub const empty_sigset = 0; | |
| 186 | 185 | pub const siginfo_t = c_long; |
| 187 | 186 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we include it here to be compatible. |
| 188 | 187 | pub const Sigaction = extern struct { |
| ... | ... | @@ -199,6 +198,10 @@ pub const Sigaction = extern struct { |
| 199 | 198 | pub const AT = struct { |
| 200 | 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 | 205 | // TODO implement sigaction |
| 203 | 206 | // right now it is just a shim to allow using start.zig code |
| 204 | 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 | 86 | pub const MSF = system.MSF; |
| 87 | 87 | pub const MSG = system.MSG; |
| 88 | 88 | pub const NAME_MAX = system.NAME_MAX; |
| 89 | pub const NSIG = system.NSIG; | |
| 89 | 90 | pub const O = system.O; |
| 90 | 91 | pub const PATH_MAX = system.PATH_MAX; |
| 91 | 92 | pub const POLL = system.POLL; |
| ... | ... | @@ -126,10 +127,8 @@ pub const timerfd_clockid_t = system.timerfd_clockid_t; |
| 126 | 127 | pub const cpu_set_t = system.cpu_set_t; |
| 127 | 128 | pub const dev_t = system.dev_t; |
| 128 | 129 | pub const dl_phdr_info = system.dl_phdr_info; |
| 129 | pub const empty_sigset = system.empty_sigset; | |
| 130 | 130 | pub const fd_t = system.fd_t; |
| 131 | 131 | pub const file_obj = system.file_obj; |
| 132 | pub const filled_sigset = system.filled_sigset; | |
| 133 | 132 | pub const gid_t = system.gid_t; |
| 134 | 133 | pub const ifreq = system.ifreq; |
| 135 | 134 | pub const ino_t = system.ino_t; |
| ... | ... | @@ -678,7 +677,8 @@ pub fn abort() noreturn { |
| 678 | 677 | raise(SIG.ABRT) catch {}; |
| 679 | 678 | |
| 680 | 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 | 683 | // Only one thread may proceed to the rest of abort(). |
| 684 | 684 | if (!builtin.single_threaded) { |
| ... | ... | @@ -691,14 +691,15 @@ pub fn abort() noreturn { |
| 691 | 691 | // Install default handler so that the tkill below will terminate. |
| 692 | 692 | const sigact = Sigaction{ |
| 693 | 693 | .handler = .{ .handler = SIG.DFL }, |
| 694 | .mask = empty_sigset, | |
| 694 | .mask = sigemptyset(), | |
| 695 | 695 | .flags = 0, |
| 696 | 696 | }; |
| 697 | 697 | sigaction(SIG.ABRT, &sigact, null); |
| 698 | 698 | |
| 699 | 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 | 703 | sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); |
| 703 | 704 | |
| 704 | 705 | // Beyond this point should be unreachable. |
| ... | ... | @@ -723,18 +724,13 @@ pub fn raise(sig: u8) RaiseError!void { |
| 723 | 724 | } |
| 724 | 725 | |
| 725 | 726 | if (native_os == .linux) { |
| 726 | // https://git.musl-libc.org/cgit/musl/commit/?id=0bed7e0acfd34e3fb63ca0e4d99b7592571355a9 | |
| 727 | // | |
| 728 | // Unlike musl, libc-less Zig std does not have any internal signals for implementation purposes, so we | |
| 729 | // need to block all signals on the assumption that any of them could potentially fork() in a handler. | |
| 730 | var set: sigset_t = undefined; | |
| 731 | sigprocmask(SIG.BLOCK, &linux.all_mask, &set); | |
| 732 | ||
| 733 | const tid = linux.gettid(); | |
| 734 | const rc = linux.tkill(tid, sig); | |
| 735 | ||
| 736 | // restore signal mask | |
| 737 | sigprocmask(SIG.SETMASK, &set, null); | |
| 727 | // Block all signals so a `fork` (from a signal handler) between the gettid() and kill() syscalls | |
| 728 | // cannot trigger an extra, unexpected, inter-process signal. Signal paranoia inherited from Musl. | |
| 729 | const filled = linux.sigfillset(); | |
| 730 | var orig: sigset_t = undefined; | |
| 731 | sigprocmask(SIG.BLOCK, &filled, &orig); | |
| 732 | const rc = linux.tkill(linux.gettid(), sig); | |
| 733 | sigprocmask(SIG.SETMASK, &orig, null); | |
| 738 | 734 | |
| 739 | 735 | switch (errno(rc)) { |
| 740 | 736 | .SUCCESS => return, |
| ... | ... | @@ -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 | 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 | 5874 | switch (errno(system.sigaction(sig, act, oact))) { |
| 5824 | 5875 | .SUCCESS => return, |
| 5825 | 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 | 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 | 885 | if (native_os == .wasi or native_os == .windows) |
| 864 | 886 | return error.SkipZigTest; |
| 865 | 887 | |
| 866 | // https://github.com/ziglang/zig/issues/7427 | |
| 867 | if (native_os == .linux and builtin.target.cpu.arch == .x86) | |
| 888 | var sigset: posix.sigset_t = posix.sigemptyset(); | |
| 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 | 917 | return error.SkipZigTest; |
| 869 | 918 | |
| 870 | 919 | // https://github.com/ziglang/zig/issues/15381 |
| ... | ... | @@ -872,66 +921,138 @@ test "sigaction" { |
| 872 | 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 | 926 | const S = struct { |
| 876 | 927 | var handler_called_count: u32 = 0; |
| 877 | 928 | |
| 878 | 929 | fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void { |
| 879 | 930 | _ = ctx_ptr; |
| 880 | 931 | // Check that we received the correct signal. |
| 881 | switch (native_os) { | |
| 882 | .netbsd => { | |
| 883 | if (sig == posix.SIG.USR1 and sig == info.info.signo) | |
| 884 | handler_called_count += 1; | |
| 885 | }, | |
| 886 | else => { | |
| 887 | if (sig == posix.SIG.USR1 and sig == info.signo) | |
| 888 | handler_called_count += 1; | |
| 889 | }, | |
| 932 | const info_sig = switch (native_os) { | |
| 933 | .netbsd => info.info.signo, | |
| 934 | else => info.signo, | |
| 935 | }; | |
| 936 | if (sig == test_signo and sig == info_sig) { | |
| 937 | handler_called_count += 1; | |
| 890 | 938 | } |
| 891 | 939 | } |
| 892 | 940 | }; |
| 893 | 941 | |
| 894 | 942 | var sa: posix.Sigaction = .{ |
| 895 | 943 | .handler = .{ .sigaction = &S.handler }, |
| 896 | .mask = posix.empty_sigset, | |
| 944 | .mask = posix.sigemptyset(), | |
| 897 | 945 | .flags = posix.SA.SIGINFO | posix.SA.RESETHAND, |
| 898 | 946 | }; |
| 947 | ||
| 899 | 948 | var old_sa: posix.Sigaction = undefined; |
| 900 | 949 | |
| 901 | 950 | // Install the new signal handler. |
| 902 | posix.sigaction(posix.SIG.USR1, &sa, null); | |
| 951 | posix.sigaction(test_signo, &sa, null); | |
| 903 | 952 | |
| 904 | 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 | 955 | try testing.expectEqual(&S.handler, old_sa.handler.sigaction.?); |
| 907 | 956 | try testing.expect((old_sa.flags & posix.SA.SIGINFO) != 0); |
| 908 | 957 | |
| 909 | 958 | // Invoke the handler. |
| 910 | try posix.raise(posix.SIG.USR1); | |
| 911 | try testing.expect(S.handler_called_count == 1); | |
| 959 | try posix.raise(test_signo); | |
| 960 | try testing.expectEqual(1, S.handler_called_count); | |
| 912 | 961 | |
| 913 | 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 | 964 | try testing.expectEqual(posix.SIG.DFL, old_sa.handler.handler); |
| 916 | 965 | |
| 917 | 966 | // Reinstall the signal w/o RESETHAND and re-raise |
| 918 | 967 | sa.flags = posix.SA.SIGINFO; |
| 919 | posix.sigaction(posix.SIG.USR1, &sa, null); | |
| 920 | try posix.raise(posix.SIG.USR1); | |
| 921 | try testing.expect(S.handler_called_count == 2); | |
| 968 | posix.sigaction(test_signo, &sa, null); | |
| 969 | try posix.raise(test_signo); | |
| 970 | try testing.expectEqual(2, S.handler_called_count); | |
| 922 | 971 | |
| 923 | 972 | // Now set the signal to ignored |
| 924 | 973 | sa.handler = .{ .handler = posix.SIG.IGN }; |
| 925 | 974 | sa.flags = 0; |
| 926 | posix.sigaction(posix.SIG.USR1, &sa, null); | |
| 975 | posix.sigaction(test_signo, &sa, null); | |
| 927 | 976 | |
| 928 | 977 | // Re-raise to ensure handler is actually ignored |
| 929 | try posix.raise(posix.SIG.USR1); | |
| 930 | try testing.expect(S.handler_called_count == 2); | |
| 978 | try posix.raise(test_signo); | |
| 979 | try testing.expectEqual(2, S.handler_called_count); | |
| 931 | 980 | |
| 932 | 981 | // Ensure that ignored state is returned when querying |
| 933 | posix.sigaction(posix.SIG.USR1, null, &old_sa); | |
| 934 | try testing.expectEqual(posix.SIG.IGN, old_sa.handler.handler.?); | |
| 982 | posix.sigaction(test_signo, null, &old_sa); | |
| 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 | 1058 | test "dup & dup2" { |
lib/std/start.zig+1-1| ... | ... | @@ -749,7 +749,7 @@ fn maybeIgnoreSigpipe() void { |
| 749 | 749 | // Set handler to a noop function instead of `SIG.IGN` to prevent |
| 750 | 750 | // leaking signal disposition to a child process. |
| 751 | 751 | .handler = .{ .handler = noopSigHandler }, |
| 752 | .mask = posix.empty_sigset, | |
| 752 | .mask = posix.sigemptyset(), | |
| 753 | 753 | .flags = 0, |
| 754 | 754 | }; |
| 755 | 755 | posix.sigaction(posix.SIG.PIPE, &act, null); |
src/crash_report.zig+2-3| ... | ... | @@ -175,12 +175,11 @@ pub fn attachSegfaultHandler() void { |
| 175 | 175 | _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); |
| 176 | 176 | return; |
| 177 | 177 | } |
| 178 | var act: posix.Sigaction = .{ | |
| 178 | const act: posix.Sigaction = .{ | |
| 179 | 179 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 180 | .mask = posix.empty_sigset, | |
| 180 | .mask = posix.sigemptyset(), | |
| 181 | 181 | .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), |
| 182 | 182 | }; |
| 183 | ||
| 184 | 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 | 18 | { |
| 19 | 19 | const act = posix.Sigaction{ |
| 20 | 20 | .handler = .{ .handler = posix.SIG.DFL }, |
| 21 | .mask = posix.empty_sigset, | |
| 21 | .mask = posix.sigemptyset(), | |
| 22 | 22 | .flags = 0, |
| 23 | 23 | }; |
| 24 | 24 | try posix.sigaction(posix.SIG.PIPE, &act, null); |