authorgravatar for pat.github@tullmann.orgPat Tullmann <pat.github@tullmann.org> 2025-04-22 14:19:06-07:00
committergravatar for pat.github@tullmann.orgPat Tullmann <pat.github@tullmann.org> 2025-04-30 20:32:04-07:00
log120c4789c31c066f15fe414a5b32cdc7e80a065c
treee45c5a1dd84791676bb8f516fc0c2c0200cfe0c0
parentf0aefa625b5b0d0b3612cfba9bd25c825a71818f

sigset_t: sigemptyset() and sigfillset() are functions that return sigset_t

By returning an initialized sigset (instead of taking the set as an output parameter), these functions can be used to directly initialize the `mask` parameter of a `Sigaction` instance.

11 files changed, 65 insertions(+), 63 deletions(-)

lib/std/Progress.zig+2-3
...@@ -410,12 +410,11 @@ pub fn start(options: Options) Node {...@@ -410,12 +410,11 @@ pub fn start(options: Options) Node {
410 }410 }
411411
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 = undefined,415 .mask = posix.sigemptyset(),
416 .flags = (posix.SA.SIGINFO | posix.SA.RESTART),416 .flags = (posix.SA.SIGINFO | posix.SA.RESTART),
417 };417 };
418 posix.sigemptyset(&act.mask);
419 posix.sigaction(posix.SIG.WINCH, &act, null);418 posix.sigaction(posix.SIG.WINCH, &act, null);
420 }419 }
421420
lib/std/debug.zig+4-7
...@@ -1387,13 +1387,11 @@ pub fn attachSegfaultHandler() void {...@@ -1387,13 +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 = undefined,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 posix.sigemptyset(&act.mask);
1396
1397 updateSegfaultHandler(&act);1395 updateSegfaultHandler(&act);
1398}1396}
13991397
...@@ -1405,12 +1403,11 @@ fn resetSegfaultHandler() void {...@@ -1405,12 +1403,11 @@ fn resetSegfaultHandler() void {
1405 }1403 }
1406 return;1404 return;
1407 }1405 }
1408 var act = posix.Sigaction{1406 const act = posix.Sigaction{
1409 .handler = .{ .handler = posix.SIG.DFL },1407 .handler = .{ .handler = posix.SIG.DFL },
1410 .mask = undefined,1408 .mask = posix.sigemptyset(),
1411 .flags = 0,1409 .flags = 0,
1412 };1410 };
1413 posix.sigemptyset(&act.mask);
1414 updateSegfaultHandler(&act);1411 updateSegfaultHandler(&act);
1415}1412}
14161413
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};
561561
562pub const sigset_t = [1024 / 32]u32;562pub const sigset_t = [1024 / 32]u32;
563pub const empty_sigset = [_]u32{0} ** @typeInfo(sigset_t).array.len;563pub fn sigemptyset() sigset_t {
564 return [_]u32{0} ** @typeInfo(sigset_t).array.len;
565}
564pub const siginfo_t = extern struct {566pub const siginfo_t = extern struct {
565 signo: i32,567 signo: i32,
566 errno: i32,568 errno: i32,
lib/std/os/linux.zig+8-4
...@@ -1800,11 +1800,15 @@ const SigsetElement = c_ulong;...@@ -1800,11 +1800,15 @@ const SigsetElement = c_ulong;
18001800
1801const sigset_len = @typeInfo(sigset_t).array.len;1801const sigset_len = @typeInfo(sigset_t).array.len;
18021802
1803/// Empty set to initialize sigset_t instances from. No need for `sigemptyset`.1803/// Zig's version of sigemptyset. Returns initialized sigset_t.
1804pub const empty_sigset: sigset_t = [_]SigsetElement{0} ** sigset_len;1804pub fn sigemptyset() sigset_t {
1805 return [_]SigsetElement{0} ** sigset_len;
1806}
18051807
1806/// Filled set to initialize sigset_t instances from. No need for `sigfillset`.1808/// Zig's version of sigfillset. Returns initalized sigset_t.
1807pub const filled_sigset: sigset_t = [_]SigsetElement{~@as(SigsetElement, 0)} ** sigset_len;1809pub fn sigfillset() sigset_t {
1810 return [_]SigsetElement{~@as(SigsetElement, 0)} ** sigset_len;
1811}
18081812
1809fn sigset_bit_index(sig: usize) struct { word: usize, mask: SigsetElement } {1813fn sigset_bit_index(sig: usize) struct { word: usize, mask: SigsetElement } {
1810 assert(sig > 0);1814 assert(sig > 0);
lib/std/os/linux/test.zig+5-7
...@@ -128,7 +128,7 @@ test "fadvise" {...@@ -128,7 +128,7 @@ test "fadvise" {
128test "sigset_t" {128test "sigset_t" {
129 std.debug.assert(@sizeOf(linux.sigset_t) == (linux.NSIG / 8));129 std.debug.assert(@sizeOf(linux.sigset_t) == (linux.NSIG / 8));
130130
131 var sigset = linux.empty_sigset;131 var sigset = linux.sigemptyset();
132132
133 // See that none are set, then set each one, see that they're all set, then133 // See that none are set, then set each one, see that they're all set, then
134 // remove them all, and then see that none are set.134 // remove them all, and then see that none are set.
...@@ -140,8 +140,6 @@ test "sigset_t" {...@@ -140,8 +140,6 @@ test "sigset_t" {
140 }140 }
141 for (1..linux.NSIG) |i| {141 for (1..linux.NSIG) |i| {
142 try expectEqual(linux.sigismember(&sigset, @truncate(i)), true);142 try expectEqual(linux.sigismember(&sigset, @truncate(i)), true);
143 try expectEqual(linux.sigismember(&linux.filled_sigset, @truncate(i)), true);
144 try expectEqual(linux.sigismember(&linux.empty_sigset, @truncate(i)), false);
145 }143 }
146 for (1..linux.NSIG) |i| {144 for (1..linux.NSIG) |i| {
147 linux.sigdelset(&sigset, @truncate(i));145 linux.sigdelset(&sigset, @truncate(i));
...@@ -183,16 +181,16 @@ test "sigset_t" {...@@ -183,16 +181,16 @@ test "sigset_t" {
183 }181 }
184}182}
185183
186test "filled_sigset" {184test "sigfillset" {
187 // unlike the C library, all the signals are set in the kernel-level fillset185 // unlike the C library, all the signals are set in the kernel-level fillset
188 const sigset = linux.filled_sigset;186 const sigset = linux.sigfillset();
189 for (1..linux.NSIG) |i| {187 for (1..linux.NSIG) |i| {
190 try expectEqual(linux.sigismember(&sigset, @truncate(i)), true);188 try expectEqual(linux.sigismember(&sigset, @truncate(i)), true);
191 }189 }
192}190}
193191
194test "empty_sigset" {192test "sigemptyset" {
195 const sigset = linux.empty_sigset;193 const sigset = linux.sigemptyset();
196 for (1..linux.NSIG) |i| {194 for (1..linux.NSIG) |i| {
197 try expectEqual(linux.sigismember(&sigset, @truncate(i)), false);195 try expectEqual(linux.sigismember(&sigset, @truncate(i)), false);
198 }196 }
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};
184pub const sigset_t = c_long;184pub const sigset_t = c_long;
185pub const empty_sigset = 0;
186pub const siginfo_t = c_long;185pub 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.
188pub const Sigaction = extern struct {187pub const Sigaction = extern struct {
...@@ -199,6 +198,10 @@ pub const Sigaction = extern struct {...@@ -199,6 +198,10 @@ pub const Sigaction = extern struct {
199pub const AT = struct {198pub const AT = struct {
200 pub const FDCWD = -100; // we just make up a constant; FDCWD and openat don't actually exist in plan9199 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.
202pub fn sigemptyset() sigset_t {
203 return 0;
204}
202// TODO implement sigaction205// TODO implement sigaction
203// right now it is just a shim to allow using start.zig code206// right now it is just a shim to allow using start.zig code
204pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize {207pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize {
lib/std/posix.zig+17-12
...@@ -677,7 +677,8 @@ pub fn abort() noreturn {...@@ -677,7 +677,8 @@ pub fn abort() noreturn {
677 raise(SIG.ABRT) catch {};677 raise(SIG.ABRT) catch {};
678678
679 // Disable all signal handlers.679 // Disable all signal handlers.
680 sigprocmask(SIG.BLOCK, &linux.filled_sigset, null);680 const filledset = linux.sigfillset();
681 sigprocmask(SIG.BLOCK, &filledset, null);
681682
682 // Only one thread may proceed to the rest of abort().683 // Only one thread may proceed to the rest of abort().
683 if (!builtin.single_threaded) {684 if (!builtin.single_threaded) {
...@@ -690,14 +691,14 @@ pub fn abort() noreturn {...@@ -690,14 +691,14 @@ pub fn abort() noreturn {
690 // Install default handler so that the tkill below will terminate.691 // Install default handler so that the tkill below will terminate.
691 const sigact = Sigaction{692 const sigact = Sigaction{
692 .handler = .{ .handler = SIG.DFL },693 .handler = .{ .handler = SIG.DFL },
693 .mask = linux.empty_sigset,694 .mask = sigemptyset(),
694 .flags = 0,695 .flags = 0,
695 };696 };
696 sigaction(SIG.ABRT, &sigact, null);697 sigaction(SIG.ABRT, &sigact, null);
697698
698 _ = linux.tkill(linux.gettid(), SIG.ABRT);699 _ = linux.tkill(linux.gettid(), SIG.ABRT);
699700
700 var sigabrtmask = linux.empty_sigset;701 var sigabrtmask = sigemptyset();
701 sigaddset(&sigabrtmask, SIG.ABRT);702 sigaddset(&sigabrtmask, SIG.ABRT);
702 sigprocmask(SIG.UNBLOCK, &sigabrtmask, null);703 sigprocmask(SIG.UNBLOCK, &sigabrtmask, null);
703704
...@@ -727,7 +728,7 @@ pub fn raise(sig: u8) RaiseError!void {...@@ -727,7 +728,7 @@ pub fn raise(sig: u8) RaiseError!void {
727 // cannot trigger an extra, unexpected, inter-process signal. Signal paranoia inherited from Musl.728 // cannot trigger an extra, unexpected, inter-process signal. Signal paranoia inherited from Musl.
728 const filled = linux.sigfillset();729 const filled = linux.sigfillset();
729 var orig: sigset_t = undefined;730 var orig: sigset_t = undefined;
730 sigprocmask(SIG.BLOCK, &linux.filled_sigset, &orig);731 sigprocmask(SIG.BLOCK, &filled, &orig);
731 const rc = linux.tkill(linux.gettid(), sig);732 const rc = linux.tkill(linux.gettid(), sig);
732 sigprocmask(SIG.SETMASK, &orig, null);733 sigprocmask(SIG.SETMASK, &orig, null);
733734
...@@ -5813,24 +5814,28 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {...@@ -5813,24 +5814,28 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
5813 }5814 }
5814}5815}
58155816
5816pub fn sigfillset(set: *sigset_t) void {5817/// Return a filled sigset_t.
5818pub fn sigfillset() sigset_t {
5817 if (builtin.link_libc) {5819 if (builtin.link_libc) {
5818 switch (errno(system.sigfillset(set))) {5820 var set: sigset_t = undefined;
5819 .SUCCESS => return,5821 switch (errno(system.sigfillset(&set))) {
5822 .SUCCESS => return set,
5820 else => unreachable,5823 else => unreachable,
5821 }5824 }
5822 }5825 }
5823 set.* = system.filled_sigset;5826 return system.sigfillset();
5824}5827}
58255828
5826pub fn sigemptyset(set: *sigset_t) void {5829/// Return an empty sigset_t.
5830pub fn sigemptyset() sigset_t {
5827 if (builtin.link_libc) {5831 if (builtin.link_libc) {
5828 switch (errno(system.sigemptyset(set))) {5832 var set: sigset_t = undefined;
5829 .SUCCESS => return,5833 switch (errno(system.sigemptyset(&set))) {
5834 .SUCCESS => return set,
5830 else => unreachable,5835 else => unreachable,
5831 }5836 }
5832 }5837 }
5833 set.* = mem.zeroes(sigset_t);5838 return system.sigemptyset();
5834}5839}
58355840
5836pub fn sigaddset(set: *sigset_t, sig: u8) void {5841pub fn sigaddset(set: *sigset_t, sig: u8) void {
lib/std/posix/test.zig+16-19
...@@ -863,17 +863,15 @@ test "sigset empty/full" {...@@ -863,17 +863,15 @@ test "sigset empty/full" {
863 if (native_os == .wasi or native_os == .windows)863 if (native_os == .wasi or native_os == .windows)
864 return error.SkipZigTest;864 return error.SkipZigTest;
865865
866 var set: posix.sigset_t = undefined;866 var set: posix.sigset_t = posix.sigemptyset();
867
868 posix.sigemptyset(&set);
869 for (1..posix.NSIG) |i| {867 for (1..posix.NSIG) |i| {
870 try expectEqual(false, posix.sigismember(&set, @truncate(i)));868 try expectEqual(false, posix.sigismember(&set, @truncate(i)));
871 }869 }
872870
873 // The C library can reserve some (unnamed) signals, so can't check the full871 // The C library can reserve some (unnamed) signals, so can't check the full
874 // NSIG set is defined, but just test a couple:872 // NSIG set is defined, but just test a couple:
875 posix.sigfillset(&set);873 set = posix.sigfillset();
876 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.USR1)));874 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.CHLD)));
877 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));875 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));
878}876}
879877
...@@ -887,8 +885,7 @@ test "sigset add/del" {...@@ -887,8 +885,7 @@ test "sigset add/del" {
887 if (native_os == .wasi or native_os == .windows)885 if (native_os == .wasi or native_os == .windows)
888 return error.SkipZigTest;886 return error.SkipZigTest;
889887
890 var sigset: posix.sigset_t = undefined;888 var sigset: posix.sigset_t = posix.sigemptyset();
891 posix.sigemptyset(&sigset);
892889
893 // See that none are set, then set each one, see that they're all set, then890 // See that none are set, then set each one, see that they're all set, then
894 // remove them all, and then see that none are set.891 // remove them all, and then see that none are set.
...@@ -924,7 +921,7 @@ test "sigaction" {...@@ -924,7 +921,7 @@ test "sigaction" {
924 return error.SkipZigTest;921 return error.SkipZigTest;
925 }922 }
926923
927 const test_signo = posix.SIG.USR1;924 const test_signo = posix.SIG.URG; // URG only because it is ignored by default in debuggers
928925
929 const S = struct {926 const S = struct {
930 var handler_called_count: u32 = 0;927 var handler_called_count: u32 = 0;
...@@ -944,10 +941,10 @@ test "sigaction" {...@@ -944,10 +941,10 @@ test "sigaction" {
944941
945 var sa: posix.Sigaction = .{942 var sa: posix.Sigaction = .{
946 .handler = .{ .sigaction = &S.handler },943 .handler = .{ .sigaction = &S.handler },
947 .mask = undefined,944 .mask = posix.sigemptyset(),
948 .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,945 .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,
949 };946 };
950 posix.sigemptyset(&sa.mask);947
951 var old_sa: posix.Sigaction = undefined;948 var old_sa: posix.Sigaction = undefined;
952949
953 // Install the new signal handler.950 // Install the new signal handler.
...@@ -1009,29 +1006,29 @@ test "sigset_t bits" {...@@ -1009,29 +1006,29 @@ test "sigset_t bits" {
10091006
1010 const self_pid = posix.system.getpid();1007 const self_pid = posix.system.getpid();
10111008
1012 // To check that sigset_t mapping matches kernel (think u32/u641009 // To check that sigset_t mapping matches kernel (think u32/u64 mismatches on
1013 // mismatches on big-endian), try sending a blocked signal to make1010 // big-endian), try sending a blocked signal to make sure the mask matches the
1014 // sure the mask matches the signal.1011 // signal. (Send URG and CHLD because they're ignored by default in the
1015 inline for ([_]usize{ posix.SIG.INT, posix.SIG.USR1, 62, 94, 126 }) |test_signo| {1012 // debugger, vs. USR1 or other named signals)
1013 inline for ([_]usize{ posix.SIG.URG, posix.SIG.CHLD, 62, 94, 126 }) |test_signo| {
1016 if (test_signo >= posix.NSIG) continue;1014 if (test_signo >= posix.NSIG) continue;
10171015
1018 S.expected_sig = test_signo;1016 S.expected_sig = test_signo;
1019 S.handler_called_count = 0;1017 S.handler_called_count = 0;
10201018
1021 var sa: posix.Sigaction = .{1019 const sa: posix.Sigaction = .{
1022 .handler = .{ .sigaction = &S.handler },1020 .handler = .{ .sigaction = &S.handler },
1023 .mask = undefined,1021 .mask = posix.sigemptyset(),
1024 .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,1022 .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,
1025 };1023 };
1026 posix.sigemptyset(&sa.mask);1024
1027 var old_sa: posix.Sigaction = undefined;1025 var old_sa: posix.Sigaction = undefined;
10281026
1029 // Install the new signal handler.1027 // Install the new signal handler.
1030 posix.sigaction(test_signo, &sa, &old_sa);1028 posix.sigaction(test_signo, &sa, &old_sa);
10311029
1032 // block the signal and see that its delayed until unblocked1030 // block the signal and see that its delayed until unblocked
1033 var block_one: posix.sigset_t = undefined;1031 var block_one: posix.sigset_t = posix.sigemptyset();
1034 posix.sigemptyset(&block_one);
1035 posix.sigaddset(&block_one, test_signo);1032 posix.sigaddset(&block_one, test_signo);
1036 posix.sigprocmask(posix.SIG.BLOCK, &block_one, null);1033 posix.sigprocmask(posix.SIG.BLOCK, &block_one, null);
10371034
lib/std/start.zig+2-3
...@@ -745,14 +745,13 @@ fn maybeIgnoreSigpipe() void {...@@ -745,14 +745,13 @@ fn maybeIgnoreSigpipe() void {
745745
746 if (have_sigpipe_support and !std.options.keep_sigpipe) {746 if (have_sigpipe_support and !std.options.keep_sigpipe) {
747 const posix = std.posix;747 const posix = std.posix;
748 var act: posix.Sigaction = .{748 const act: posix.Sigaction = .{
749 // Set handler to a noop function instead of `SIG.IGN` to prevent749 // 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 = undefined,752 .mask = posix.sigemptyset(),
753 .flags = 0,753 .flags = 0,
754 };754 };
755 posix.sigemptyset(&act.mask);
756 posix.sigaction(posix.SIG.PIPE, &act, null);755 posix.sigaction(posix.SIG.PIPE, &act, null);
757 }756 }
758}757}
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 = undefined,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 posix.sigemptyset(&act.mask);
184 debug.updateSegfaultHandler(&act);183 debug.updateSegfaultHandler(&act);
185}184}
186185
test/standalone/sigpipe/build.zig+2-3
...@@ -16,12 +16,11 @@ pub fn build(b: *std.build.Builder) !void {...@@ -16,12 +16,11 @@ pub fn build(b: *std.build.Builder) !void {
16 // This test runs "breakpipe" as a child process and that process16 // This test runs "breakpipe" as a child process and that process
17 // depends on inheriting a SIGPIPE disposition of "default".17 // depends on inheriting a SIGPIPE disposition of "default".
18 {18 {
19 var act = posix.Sigaction{19 const act = posix.Sigaction{
20 .handler = .{ .handler = posix.SIG.DFL },20 .handler = .{ .handler = posix.SIG.DFL },
21 .mask = undefined,21 .mask = posix.sigemptyset(),
22 .flags = 0,22 .flags = 0,
23 };23 };
24 posix.sigemptyset(&act.mask);
25 try posix.sigaction(posix.SIG.PIPE, &act, null);24 try posix.sigaction(posix.SIG.PIPE, &act, null);
26 }25 }
2726