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
This commit is contained in:
Pat Tullmann 2025-04-28 21:03:23 -07:00 committed by Alex Rønne Petersen
parent 85a6b75e18
commit 6eb5e56306
4 changed files with 44 additions and 2 deletions

View file

@ -10347,6 +10347,16 @@ pub const sigaction = switch (native_os) {
else => private.sigaction,
};
/// Zig's version of SIGRTMIN. Actually a function.
pub fn sigrtmin() u8 {
return @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmin())));
}
/// Zig's version of SIGRTMAX. Actually a function.
pub fn sigrtmax() u8 {
return @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmax())));
}
pub const sigfillset = switch (native_os) {
.netbsd => private.__sigfillset14,
else => private.sigfillset,
@ -11213,6 +11223,9 @@ const private = struct {
extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;
extern "c" fn __sigaltstack14(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
extern "c" fn __libc_current_sigrtmin() c_int;
extern "c" fn __libc_current_sigrtmax() c_int;
// Don't forget to add another clown when an OS picks yet another unique
// symbol name for errno location!
// 🤡🤡🤡🤡🤡🤡

View file

@ -1801,6 +1801,19 @@ const SigsetElement = c_ulong;
const sigset_len = @typeInfo(sigset_t).array.len;
/// Zig's SIGRTMIN, but is a function for compatibility with glibc
pub fn sigrtmin() u8 {
// Default is 32 in the kernel UAPI: https://github.com/torvalds/linux/blob/78109c591b806e41987e0b83390e61d675d1f724/include/uapi/asm-generic/signal.h#L50
// AFAICT, all architectures that override this also set it to 32:
// https://github.com/search?q=repo%3Atorvalds%2Flinux+sigrtmin+path%3Auapi&type=code
return 32;
}
/// Zig's SIGRTMAX, but is a function for compatibility with glibc
pub fn sigrtmax() u8 {
return NSIG - 1;
}
/// Zig's version of sigemptyset. Returns initialized sigset_t.
pub fn sigemptyset() sigset_t {
return [_]SigsetElement{0} ** sigset_len;

View file

@ -151,6 +151,8 @@ pub const rusage = system.rusage;
pub const sa_family_t = system.sa_family_t;
pub const siginfo_t = system.siginfo_t;
pub const sigset_t = system.sigset_t;
pub const sigrtmin = system.sigrtmin;
pub const sigrtmax = system.sigrtmax;
pub const sockaddr = system.sockaddr;
pub const socklen_t = system.socklen_t;
pub const stack_t = system.stack_t;

View file

@ -859,6 +859,17 @@ test "shutdown socket" {
std.net.Stream.close(.{ .handle = sock });
}
test "sigrtmin/max" {
if (native_os == .wasi or native_os == .windows or native_os == .macos) {
return error.SkipZigTest;
}
try std.testing.expect(posix.sigrtmin() >= 32);
try std.testing.expect(posix.sigrtmin() >= posix.system.sigrtmin());
try std.testing.expect(posix.sigrtmin() < posix.system.sigrtmax());
try std.testing.expect(posix.sigrtmax() < posix.NSIG);
}
test "sigset empty/full" {
if (native_os == .wasi or native_os == .windows)
return error.SkipZigTest;
@ -875,10 +886,13 @@ test "sigset empty/full" {
try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));
}
// Some signals (32 - 34 on glibc/musl) are not allowed to be added to a
// Some signals (i.e., 32 - 34 on glibc/musl) are not allowed to be added to a
// sigset by the C library, so avoid testing them.
fn reserved_signo(i: usize) bool {
return builtin.link_libc and (i >= 32 and i <= 34);
if (native_os == .macos) {
return false;
}
return builtin.link_libc and (i >= 32 and i < posix.sigrtmin());
}
test "sigset add/del" {