authorgravatar for pat.github@tullmann.orgPat Tullmann <pat.github@tullmann.org> 2025-04-28 21:03:23-07:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-05-09 15:10:25+02:00
log6eb5e56306620e72ae80d7ad6626f8d0ceb24af5
tree2ca4383369165a41814d3b95f148e86f46627920
parent85a6b75e18248bad83437323cab14fe1973057ec

std.posix: Add sigrtmin() and sigrtmax()

For C code the macros SIGRTMIN and SIGRTMAX provide these values. In practice what looks like a constant is actually provided by a libc call. So the Zig implementations are explicitly function calls. glibc (and Musl) export a run-time minimum "real-time" signal number, based on how many signals are reserved for internal implementation details (generally threading). In practice, on Linux, sigrtmin() is 35 on glibc with the older LinuxThread and 34 with the newer NPTL-based implementation. Musl always returns 35. The maximum "real-time" signal number is NSIG - 1 (64 on most Linux kernels, but 128 on MIPS). When not linking a C Library, Zig can report the full range of "rt" signals (none are reserved by Zig). Fixes #21189

4 files changed, 44 insertions(+), 2 deletions(-)

lib/std/c.zig+13
...@@ -10347,6 +10347,16 @@ pub const sigaction = switch (native_os) {...@@ -10347,6 +10347,16 @@ pub const sigaction = switch (native_os) {
10347 else => private.sigaction,10347 else => private.sigaction,
10348};10348};
1034910349
10350/// Zig's version of SIGRTMIN. Actually a function.
10351pub fn sigrtmin() u8 {
10352 return @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmin())));
10353}
10354
10355/// Zig's version of SIGRTMAX. Actually a function.
10356pub fn sigrtmax() u8 {
10357 return @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmax())));
10358}
10359
10350pub const sigfillset = switch (native_os) {10360pub const sigfillset = switch (native_os) {
10351 .netbsd => private.__sigfillset14,10361 .netbsd => private.__sigfillset14,
10352 else => private.sigfillset,10362 else => private.sigfillset,
...@@ -11213,6 +11223,9 @@ const private = struct {...@@ -11213,6 +11223,9 @@ const private = struct {
11213 extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;11223 extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;
11214 extern "c" fn __sigaltstack14(ss: ?*stack_t, old_ss: ?*stack_t) c_int;11224 extern "c" fn __sigaltstack14(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
1121511225
11226 extern "c" fn __libc_current_sigrtmin() c_int;
11227 extern "c" fn __libc_current_sigrtmax() c_int;
11228
11216 // Don't forget to add another clown when an OS picks yet another unique11229 // Don't forget to add another clown when an OS picks yet another unique
11217 // symbol name for errno location!11230 // symbol name for errno location!
11218 // 🤡🤡🤡🤡🤡🤡11231 // 🤡🤡🤡🤡🤡🤡
lib/std/os/linux.zig+13
...@@ -1801,6 +1801,19 @@ const SigsetElement = c_ulong;...@@ -1801,6 +1801,19 @@ const SigsetElement = c_ulong;
18011801
1802const sigset_len = @typeInfo(sigset_t).array.len;1802const sigset_len = @typeInfo(sigset_t).array.len;
18031803
1804/// Zig's SIGRTMIN, but is a function for compatibility with glibc
1805pub fn sigrtmin() u8 {
1806 // Default is 32 in the kernel UAPI: https://github.com/torvalds/linux/blob/78109c591b806e41987e0b83390e61d675d1f724/include/uapi/asm-generic/signal.h#L50
1807 // AFAICT, all architectures that override this also set it to 32:
1808 // https://github.com/search?q=repo%3Atorvalds%2Flinux+sigrtmin+path%3Auapi&type=code
1809 return 32;
1810}
1811
1812/// Zig's SIGRTMAX, but is a function for compatibility with glibc
1813pub fn sigrtmax() u8 {
1814 return NSIG - 1;
1815}
1816
1804/// Zig's version of sigemptyset. Returns initialized sigset_t.1817/// Zig's version of sigemptyset. Returns initialized sigset_t.
1805pub fn sigemptyset() sigset_t {1818pub fn sigemptyset() sigset_t {
1806 return [_]SigsetElement{0} ** sigset_len;1819 return [_]SigsetElement{0} ** sigset_len;
lib/std/posix.zig+2
...@@ -151,6 +151,8 @@ pub const rusage = system.rusage;...@@ -151,6 +151,8 @@ pub const rusage = system.rusage;
151pub const sa_family_t = system.sa_family_t;151pub const sa_family_t = system.sa_family_t;
152pub const siginfo_t = system.siginfo_t;152pub const siginfo_t = system.siginfo_t;
153pub const sigset_t = system.sigset_t;153pub const sigset_t = system.sigset_t;
154pub const sigrtmin = system.sigrtmin;
155pub const sigrtmax = system.sigrtmax;
154pub const sockaddr = system.sockaddr;156pub const sockaddr = system.sockaddr;
155pub const socklen_t = system.socklen_t;157pub const socklen_t = system.socklen_t;
156pub const stack_t = system.stack_t;158pub const stack_t = system.stack_t;
lib/std/posix/test.zig+16-2
...@@ -859,6 +859,17 @@ test "shutdown socket" {...@@ -859,6 +859,17 @@ test "shutdown socket" {
859 std.net.Stream.close(.{ .handle = sock });859 std.net.Stream.close(.{ .handle = sock });
860}860}
861861
862test "sigrtmin/max" {
863 if (native_os == .wasi or native_os == .windows or native_os == .macos) {
864 return error.SkipZigTest;
865 }
866
867 try std.testing.expect(posix.sigrtmin() >= 32);
868 try std.testing.expect(posix.sigrtmin() >= posix.system.sigrtmin());
869 try std.testing.expect(posix.sigrtmin() < posix.system.sigrtmax());
870 try std.testing.expect(posix.sigrtmax() < posix.NSIG);
871}
872
862test "sigset empty/full" {873test "sigset empty/full" {
863 if (native_os == .wasi or native_os == .windows)874 if (native_os == .wasi or native_os == .windows)
864 return error.SkipZigTest;875 return error.SkipZigTest;
...@@ -875,10 +886,13 @@ test "sigset empty/full" {...@@ -875,10 +886,13 @@ test "sigset empty/full" {
875 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));886 try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));
876}887}
877888
878// Some signals (32 - 34 on glibc/musl) are not allowed to be added to a889// Some signals (i.e., 32 - 34 on glibc/musl) are not allowed to be added to a
879// sigset by the C library, so avoid testing them.890// sigset by the C library, so avoid testing them.
880fn reserved_signo(i: usize) bool {891fn reserved_signo(i: usize) bool {
881 return builtin.link_libc and (i >= 32 and i <= 34);892 if (native_os == .macos) {
893 return false;
894 }
895 return builtin.link_libc and (i >= 32 and i < posix.sigrtmin());
882}896}
883897
884test "sigset add/del" {898test "sigset add/del" {