zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 95ecd521b8f169a80e543f8a07aef4807a1d46d8 (tree)
parent 11c1ddfc977957e3ef9fd10512fffab768b4922a
Author: Veikka Tuominen <git@vexu.eu>
Date:   Wed,  9 Nov 2022 17:36:40 +0200

Merge pull request #13418 from ryanschneider/signal-alignment-13216

std.os: fix alignment of Sigaction.handler_fn
Diffstat:
Mlib/std/c/darwin.zig | 2+-
Mlib/std/c/dragonfly.zig | 2+-
Mlib/std/c/freebsd.zig | 2+-
Mlib/std/c/haiku.zig | 2+-
Mlib/std/c/netbsd.zig | 2+-
Mlib/std/c/openbsd.zig | 2+-
Mlib/std/c/solaris.zig | 2+-
Mlib/std/os/linux.zig | 4++--
Mlib/std/os/test.zig | 35+++++++++++++++++++++++++++++------
9 files changed, 38 insertions(+), 15 deletions(-)

diff --git 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 { diff --git 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_failed = true; - 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_failed = false; + handler_called_count += 1; }, else => { if (sig == os.SIG.USR1 and sig == info.signo) - signal_test_failed = false; + handler_called_count += 1; }, } } @@ -774,18 +774,41 @@ 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_failed == false); - // 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); + + // 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); + + // Re-raise to ensure handler is actually ignored + try os.raise(os.SIG.USR1); + 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.?); } test "dup & dup2" {