From 64b3ffd8ffb970ca881827a21ef6546f7ad6de99 Mon Sep 17 00:00:00 2001 From: Ryan Schneider Date: Wed, 2 Nov 2022 17:11:02 -0700 Subject: [PATCH 1/3] std.os: Add IGN coverage to sigaction tests * Should start failing on aarch64 and other word-aligned CPUs. --- lib/std/os/test.zig | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index a8497586f969..ef75058140f4 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -739,7 +739,7 @@ test "shutdown socket" { os.closeSocket(sock); } -var signal_test_failed = true; +var signal_test_handler_called_count: u32 = 0; test "sigaction" { if (native_os == .wasi or native_os == .windows) @@ -756,11 +756,11 @@ test "sigaction" { switch (native_os) { .netbsd => { if (sig == os.SIG.USR1 and sig == info.info.signo) - signal_test_failed = false; + signal_test_handler_called_count += 1; }, else => { if (sig == os.SIG.USR1 and sig == info.signo) - signal_test_failed = false; + signal_test_handler_called_count += 1; }, } } @@ -782,10 +782,19 @@ test "sigaction" { try testing.expect((old_sa.flags & os.SA.SIGINFO) != 0); // Invoke the handler. try os.raise(os.SIG.USR1); - try testing.expect(signal_test_failed == false); + try testing.expect(signal_test_handler_called_count == 1); // Check if the handler has been correctly reset to SIG_DFL try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(os.SIG.DFL, old_sa.handler.handler); + // ensure we can ignore a signal + sa.handler = .{ .handler = os.SIG.IGN }; + try os.sigaction(os.SIG.USR1, &sa, null); + // and ensure it is now ignored + try os.raise(os.SIG.USR1); + try testing.expect(signal_test_handler_called_count == 1); + // and that ignored state is returned when querying + try os.sigaction(os.SIG.USR1, null, &old_sa); + try testing.expectEqual(os.SIG.IGN, old_sa.handler.handler.?); } test "dup & dup2" { From 7f1f2e653d6f3cd541e92727f2001596935f3c62 Mon Sep 17 00:00:00 2001 From: Ryan Schneider Date: Wed, 2 Nov 2022 18:55:17 -0700 Subject: [PATCH 2/3] std.os: fix alignment of Sigaction.handler_fn Fixes #13216 --- lib/std/c/darwin.zig | 2 +- lib/std/c/dragonfly.zig | 2 +- lib/std/c/freebsd.zig | 2 +- lib/std/c/haiku.zig | 2 +- lib/std/c/netbsd.zig | 2 +- lib/std/c/openbsd.zig | 2 +- lib/std/c/solaris.zig | 2 +- lib/std/os/linux.zig | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index 17a4957e94d1..9c455141f603 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -918,7 +918,7 @@ pub const siginfo_t = extern struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); handler: extern union { diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig index ddc0db270983..8c6ecb653f53 100644 --- a/lib/std/c/dragonfly.zig +++ b/lib/std/c/dragonfly.zig @@ -681,7 +681,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; pub const sig_atomic_t = c_int; pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); /// signal handler diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 799040c38120..24fce4af6eb1 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -1197,7 +1197,7 @@ const NSIG = 32; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); /// signal handler diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index 30ab3542b988..82f0c92c51ab 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -742,7 +742,7 @@ const NSIG = 32; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (i32) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (i32) align(1) callconv(.C) void); /// signal handler __sigaction_u: extern union { diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig index 18ed7027918f..132c9a606548 100644 --- a/lib/std/c/netbsd.zig +++ b/lib/std/c/netbsd.zig @@ -971,7 +971,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); /// signal handler diff --git a/lib/std/c/openbsd.zig b/lib/std/c/openbsd.zig index d78b679a1c2f..3aea81f469e2 100644 --- a/lib/std/c/openbsd.zig +++ b/lib/std/c/openbsd.zig @@ -1026,7 +1026,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); /// signal handler diff --git a/lib/std/c/solaris.zig b/lib/std/c/solaris.zig index b733b53b3d04..d45365a2b641 100644 --- a/lib/std/c/solaris.zig +++ b/lib/std/c/solaris.zig @@ -952,7 +952,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); /// signal options diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index da9ea7432744..c30fdcfbef17 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -3130,7 +3130,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; const k_sigaction_funcs = struct { - const handler = ?std.meta.FnPtr(fn (c_int) callconv(.C) void); + const handler = ?std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); const restorer = std.meta.FnPtr(fn () callconv(.C) void); }; @@ -3157,7 +3157,7 @@ pub const k_sigaction = switch (native_arch) { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = std.meta.FnPtr(fn (c_int) callconv(.C) void); + pub const handler_fn = std.meta.FnPtr(fn (c_int) align(1) callconv(.C) void); pub const sigaction_fn = std.meta.FnPtr(fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void); handler: extern union { From a68b27c252669f3a42b8f789359893ee82cd0aad Mon Sep 17 00:00:00 2001 From: Ryan Schneider Date: Thu, 3 Nov 2022 08:43:56 -0700 Subject: [PATCH 3/3] std.os: improve sigaction test coverage. --- lib/std/os/test.zig | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index ef75058140f4..c6e63fcb57bc 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -739,8 +739,6 @@ test "shutdown socket" { os.closeSocket(sock); } -var signal_test_handler_called_count: u32 = 0; - test "sigaction" { if (native_os == .wasi or native_os == .windows) return error.SkipZigTest; @@ -750,17 +748,19 @@ test "sigaction" { return error.SkipZigTest; const S = struct { + var handler_called_count: u32 = 0; + fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) void { _ = ctx_ptr; // Check that we received the correct signal. switch (native_os) { .netbsd => { if (sig == os.SIG.USR1 and sig == info.info.signo) - signal_test_handler_called_count += 1; + handler_called_count += 1; }, else => { if (sig == os.SIG.USR1 and sig == info.signo) - signal_test_handler_called_count += 1; + handler_called_count += 1; }, } } @@ -774,25 +774,39 @@ test "sigaction" { .flags = os.SA.SIGINFO | os.SA.RESETHAND, }; var old_sa: os.Sigaction = undefined; + // Install the new signal handler. try os.sigaction(os.SIG.USR1, &sa, null); + // Check that we can read it back correctly. try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(actual_handler, old_sa.handler.sigaction.?); try testing.expect((old_sa.flags & os.SA.SIGINFO) != 0); + // Invoke the handler. try os.raise(os.SIG.USR1); - try testing.expect(signal_test_handler_called_count == 1); - // Check if the handler has been correctly reset to SIG_DFL + try testing.expect(S.handler_called_count == 1); + + // Check if passing RESETHAND correctly reset the handler to SIG_DFL try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(os.SIG.DFL, old_sa.handler.handler); - // ensure we can ignore a signal + + // Reinstall the signal w/o RESETHAND and re-raise + sa.flags = os.SA.SIGINFO; + try os.sigaction(os.SIG.USR1, &sa, null); + try os.raise(os.SIG.USR1); + try testing.expect(S.handler_called_count == 2); + + // Now set the signal to ignored sa.handler = .{ .handler = os.SIG.IGN }; + sa.flags = 0; try os.sigaction(os.SIG.USR1, &sa, null); - // and ensure it is now ignored + + // Re-raise to ensure handler is actually ignored try os.raise(os.SIG.USR1); - try testing.expect(signal_test_handler_called_count == 1); - // and that ignored state is returned when querying + try testing.expect(S.handler_called_count == 2); + + // Ensure that ignored state is returned when querying try os.sigaction(os.SIG.USR1, null, &old_sa); try testing.expectEqual(os.SIG.IGN, old_sa.handler.handler.?); }