Skip to content

Commit 6eb5e56

Browse files
rootbeeralexrp
authored andcommitted
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
1 parent 85a6b75 commit 6eb5e56

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

lib/std/c.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10347,6 +10347,16 @@ pub const sigaction = switch (native_os) {
1034710347
else => private.sigaction,
1034810348
};
1034910349

10350+
/// Zig's version of SIGRTMIN. Actually a function.
10351+
pub 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.
10356+
pub fn sigrtmax() u8 {
10357+
return @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmax())));
10358+
}
10359+
1035010360
pub const sigfillset = switch (native_os) {
1035110361
.netbsd => private.__sigfillset14,
1035210362
else => private.sigfillset,
@@ -11213,6 +11223,9 @@ const private = struct {
1121311223
extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;
1121411224
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+
1121611229
// Don't forget to add another clown when an OS picks yet another unique
1121711230
// symbol name for errno location!
1121811231
// 🤡🤡🤡🤡🤡🤡

lib/std/os/linux.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,19 @@ const SigsetElement = c_ulong;
18011801

18021802
const sigset_len = @typeInfo(sigset_t).array.len;
18031803

1804+
/// Zig's SIGRTMIN, but is a function for compatibility with glibc
1805+
pub 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
1813+
pub fn sigrtmax() u8 {
1814+
return NSIG - 1;
1815+
}
1816+
18041817
/// Zig's version of sigemptyset. Returns initialized sigset_t.
18051818
pub fn sigemptyset() sigset_t {
18061819
return [_]SigsetElement{0} ** sigset_len;

lib/std/posix.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ pub const rusage = system.rusage;
151151
pub const sa_family_t = system.sa_family_t;
152152
pub const siginfo_t = system.siginfo_t;
153153
pub const sigset_t = system.sigset_t;
154+
pub const sigrtmin = system.sigrtmin;
155+
pub const sigrtmax = system.sigrtmax;
154156
pub const sockaddr = system.sockaddr;
155157
pub const socklen_t = system.socklen_t;
156158
pub const stack_t = system.stack_t;

lib/std/posix/test.zig

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,17 @@ test "shutdown socket" {
859859
std.net.Stream.close(.{ .handle = sock });
860860
}
861861

862+
test "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+
862873
test "sigset empty/full" {
863874
if (native_os == .wasi or native_os == .windows)
864875
return error.SkipZigTest;
@@ -875,10 +886,13 @@ test "sigset empty/full" {
875886
try expectEqual(true, posix.sigismember(&set, @truncate(posix.SIG.INT)));
876887
}
877888

878-
// Some signals (32 - 34 on glibc/musl) are not allowed to be added to a
889+
// Some signals (i.e., 32 - 34 on glibc/musl) are not allowed to be added to a
879890
// sigset by the C library, so avoid testing them.
880891
fn 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());
882896
}
883897

884898
test "sigset add/del" {

0 commit comments

Comments
 (0)