Commit bd4617033e
Changed files (2)
lib
std
posix
test
standalone
posix
lib/std/posix/test.zig
@@ -703,153 +703,6 @@ test "sigset add/del" {
}
}
-test "sigaction" {
- if (native_os == .wasi or native_os == .windows)
- return error.SkipZigTest;
-
- // https://github.com/ziglang/zig/issues/15381
- if (native_os == .macos and builtin.target.cpu.arch == .x86_64) {
- return error.SkipZigTest;
- }
-
- const test_signo = posix.SIG.URG; // URG only because it is ignored by default in debuggers
-
- const S = struct {
- var handler_called_count: u32 = 0;
-
- fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void {
- _ = ctx_ptr;
- // Check that we received the correct signal.
- const info_sig = switch (native_os) {
- .netbsd => info.info.signo,
- else => info.signo,
- };
- if (sig == test_signo and sig == info_sig) {
- handler_called_count += 1;
- }
- }
- };
-
- var sa: posix.Sigaction = .{
- .handler = .{ .sigaction = &S.handler },
- .mask = posix.sigemptyset(),
- .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,
- };
-
- var old_sa: posix.Sigaction = undefined;
-
- // Install the new signal handler.
- posix.sigaction(test_signo, &sa, null);
-
- // Check that we can read it back correctly.
- posix.sigaction(test_signo, null, &old_sa);
- try testing.expectEqual(&S.handler, old_sa.handler.sigaction.?);
- try testing.expect((old_sa.flags & posix.SA.SIGINFO) != 0);
-
- // Invoke the handler.
- try posix.raise(test_signo);
- try testing.expectEqual(1, S.handler_called_count);
-
- // Check if passing RESETHAND correctly reset the handler to SIG_DFL
- posix.sigaction(test_signo, null, &old_sa);
- try testing.expectEqual(posix.SIG.DFL, old_sa.handler.handler);
-
- // Reinstall the signal w/o RESETHAND and re-raise
- sa.flags = posix.SA.SIGINFO;
- posix.sigaction(test_signo, &sa, null);
- try posix.raise(test_signo);
- try testing.expectEqual(2, S.handler_called_count);
-
- // Now set the signal to ignored
- sa.handler = .{ .handler = posix.SIG.IGN };
- sa.flags = 0;
- posix.sigaction(test_signo, &sa, null);
-
- // Re-raise to ensure handler is actually ignored
- try posix.raise(test_signo);
- try testing.expectEqual(2, S.handler_called_count);
-
- // Ensure that ignored state is returned when querying
- posix.sigaction(test_signo, null, &old_sa);
- try testing.expectEqual(posix.SIG.IGN, old_sa.handler.handler);
-}
-
-test "sigset_t bits" {
- if (native_os == .wasi or native_os == .windows)
- return error.SkipZigTest;
-
- const NO_SIG: i32 = 0;
-
- const S = struct {
- var expected_sig: i32 = undefined;
- var seen_sig: i32 = NO_SIG;
-
- fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void {
- _ = ctx_ptr;
-
- const info_sig = switch (native_os) {
- .netbsd => info.info.signo,
- else => info.signo,
- };
- if (seen_sig == NO_SIG and sig == expected_sig and sig == info_sig) {
- seen_sig = sig;
- }
- }
- };
-
- // Assume this is a single-threaded process where the current thread has the
- // 'pid' thread id. (The sigprocmask calls are thread-private state.)
- const self_tid = posix.system.getpid();
-
- // To check that sigset_t mapping matches kernel (think u32/u64 mismatches on
- // big-endian), try sending a blocked signal to make sure the mask matches the
- // signal. (Send URG and CHLD because they're ignored by default in the
- // debugger, vs. USR1 or other named signals)
- inline for ([_]i32{ posix.SIG.URG, posix.SIG.CHLD, 62, 94, 126 }) |test_signo| {
- if (test_signo >= posix.NSIG) continue;
-
- S.expected_sig = test_signo;
- S.seen_sig = NO_SIG;
-
- const sa: posix.Sigaction = .{
- .handler = .{ .sigaction = &S.handler },
- .mask = posix.sigemptyset(),
- .flags = posix.SA.SIGINFO | posix.SA.RESETHAND,
- };
-
- var old_sa: posix.Sigaction = undefined;
-
- // Install the new signal handler.
- posix.sigaction(test_signo, &sa, &old_sa);
-
- // block the signal and see that its delayed until unblocked
- var block_one: posix.sigset_t = posix.sigemptyset();
- posix.sigaddset(&block_one, test_signo);
- posix.sigprocmask(posix.SIG.BLOCK, &block_one, null);
-
- // qemu maps target signals to host signals 1-to-1, so targets
- // with more signals than the host will fail to send the signal.
- const rc = posix.system.kill(self_tid, test_signo);
- switch (posix.errno(rc)) {
- .SUCCESS => {
- // See that the signal is blocked, then unblocked
- try testing.expectEqual(NO_SIG, S.seen_sig);
- posix.sigprocmask(posix.SIG.UNBLOCK, &block_one, null);
- try testing.expectEqual(test_signo, S.seen_sig);
- },
- .INVAL => {
- // Signal won't get delviered. Just clean up.
- posix.sigprocmask(posix.SIG.UNBLOCK, &block_one, null);
- try testing.expectEqual(NO_SIG, S.seen_sig);
- },
- else => |errno| return posix.unexpectedErrno(errno),
- }
-
- // Restore original handler
- posix.sigaction(test_signo, &old_sa, null);
- }
-}
-
test "dup & dup2" {
switch (native_os) {
.linux, .solaris, .illumos => {},
test/standalone/posix/sigaction.zig
@@ -1,1 +1,153 @@
-pub fn main() !void {}
+const std = @import("std");
+const builtin = @import("builtin");
+
+const native_os = builtin.target.os.tag;
+
+pub fn main() !void {
+ if (native_os == .wasi or native_os == .windows) {
+ return; // no sigaction
+ }
+
+ try test_sigaction();
+ try test_sigset_bits();
+}
+
+fn test_sigaction() !void {
+ if (native_os == .macos and builtin.target.cpu.arch == .x86_64) {
+ return; // https://github.com/ziglang/zig/issues/15381
+ }
+
+ const test_signo = std.posix.SIG.URG; // URG only because it is ignored by default in debuggers
+
+ const S = struct {
+ var handler_called_count: u32 = 0;
+
+ fn handler(sig: i32, info: *const std.posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void {
+ _ = ctx_ptr;
+ // Check that we received the correct signal.
+ const info_sig = switch (native_os) {
+ .netbsd => info.info.signo,
+ else => info.signo,
+ };
+ if (sig == test_signo and sig == info_sig) {
+ handler_called_count += 1;
+ }
+ }
+ };
+
+ var sa: std.posix.Sigaction = .{
+ .handler = .{ .sigaction = &S.handler },
+ .mask = std.posix.sigemptyset(),
+ .flags = std.posix.SA.SIGINFO | std.posix.SA.RESETHAND,
+ };
+
+ var old_sa: std.posix.Sigaction = undefined;
+
+ // Install the new signal handler.
+ std.posix.sigaction(test_signo, &sa, null);
+
+ // Check that we can read it back correctly.
+ std.posix.sigaction(test_signo, null, &old_sa);
+ try std.testing.expectEqual(&S.handler, old_sa.handler.sigaction.?);
+ try std.testing.expect((old_sa.flags & std.posix.SA.SIGINFO) != 0);
+
+ // Invoke the handler.
+ try std.posix.raise(test_signo);
+ try std.testing.expectEqual(1, S.handler_called_count);
+
+ // Check if passing RESETHAND correctly reset the handler to SIG_DFL
+ std.posix.sigaction(test_signo, null, &old_sa);
+ try std.testing.expectEqual(std.posix.SIG.DFL, old_sa.handler.handler);
+
+ // Reinstall the signal w/o RESETHAND and re-raise
+ sa.flags = std.posix.SA.SIGINFO;
+ std.posix.sigaction(test_signo, &sa, null);
+ try std.posix.raise(test_signo);
+ try std.testing.expectEqual(2, S.handler_called_count);
+
+ // Now set the signal to ignored
+ sa.handler = .{ .handler = std.posix.SIG.IGN };
+ sa.flags = 0;
+ std.posix.sigaction(test_signo, &sa, null);
+
+ // Re-raise to ensure handler is actually ignored
+ try std.posix.raise(test_signo);
+ try std.testing.expectEqual(2, S.handler_called_count);
+
+ // Ensure that ignored state is returned when querying
+ std.posix.sigaction(test_signo, null, &old_sa);
+ try std.testing.expectEqual(std.posix.SIG.IGN, old_sa.handler.handler);
+}
+
+fn test_sigset_bits() !void {
+ const NO_SIG: i32 = 0;
+
+ const S = struct {
+ var expected_sig: i32 = undefined;
+ var seen_sig: i32 = NO_SIG;
+
+ fn handler(sig: i32, info: *const std.posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) void {
+ _ = ctx_ptr;
+
+ const info_sig = switch (native_os) {
+ .netbsd => info.info.signo,
+ else => info.signo,
+ };
+ if (seen_sig == NO_SIG and sig == expected_sig and sig == info_sig) {
+ seen_sig = sig;
+ }
+ }
+ };
+
+ // Assume this is a single-threaded process where the current thread has the
+ // 'pid' thread id. (The sigprocmask calls are thread-private state.)
+ const self_tid = std.posix.system.getpid();
+
+ // To check that sigset_t mapping matches kernel (think u32/u64 mismatches on
+ // big-endian), try sending a blocked signal to make sure the mask matches the
+ // signal. (Send URG and CHLD because they're ignored by default in the
+ // debugger, vs. USR1 or other named signals)
+ inline for ([_]i32{ std.posix.SIG.URG, std.posix.SIG.CHLD, 62, 94, 126 }) |test_signo| {
+ if (test_signo >= std.posix.NSIG) continue;
+
+ S.expected_sig = test_signo;
+ S.seen_sig = NO_SIG;
+
+ const sa: std.posix.Sigaction = .{
+ .handler = .{ .sigaction = &S.handler },
+ .mask = std.posix.sigemptyset(),
+ .flags = std.posix.SA.SIGINFO | std.posix.SA.RESETHAND,
+ };
+
+ var old_sa: std.posix.Sigaction = undefined;
+
+ // Install the new signal handler.
+ std.posix.sigaction(test_signo, &sa, &old_sa);
+
+ // block the signal and see that its delayed until unblocked
+ var block_one: std.posix.sigset_t = std.posix.sigemptyset();
+ std.posix.sigaddset(&block_one, test_signo);
+ std.posix.sigprocmask(std.posix.SIG.BLOCK, &block_one, null);
+
+ // qemu maps target signals to host signals 1-to-1, so targets
+ // with more signals than the host will fail to send the signal.
+ const rc = std.posix.system.kill(self_tid, test_signo);
+ switch (std.posix.errno(rc)) {
+ .SUCCESS => {
+ // See that the signal is blocked, then unblocked
+ try std.testing.expectEqual(NO_SIG, S.seen_sig);
+ std.posix.sigprocmask(std.posix.SIG.UNBLOCK, &block_one, null);
+ try std.testing.expectEqual(test_signo, S.seen_sig);
+ },
+ .INVAL => {
+ // Signal won't get delviered. Just clean up.
+ std.posix.sigprocmask(std.posix.SIG.UNBLOCK, &block_one, null);
+ try std.testing.expectEqual(NO_SIG, S.seen_sig);
+ },
+ else => |errno| return std.posix.unexpectedErrno(errno),
+ }
+
+ // Restore original handler
+ std.posix.sigaction(test_signo, &old_sa, null);
+ }
+}