From beae3cea178a0a93c25164e992e01c7b5b78e4d7 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 12 Dec 2020 13:57:25 +0100 Subject: [PATCH 01/10] std: Improve sigaction interface Add a smoke test to prevent regressions. --- lib/std/c.zig | 6 ++--- lib/std/os.zig | 2 +- lib/std/os/bits/linux.zig | 6 ++--- lib/std/os/linux.zig | 47 ++++++++++++++++++++++----------------- lib/std/os/test.zig | 30 +++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 27 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 5ebbb9dd22..a8ac19053d 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -200,7 +200,7 @@ pub usingnamespace switch (builtin.os.tag) { pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; pub extern "c" fn sched_yield() c_int; - pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; + pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; @@ -215,7 +215,7 @@ pub usingnamespace switch (builtin.os.tag) { pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; pub extern "c" fn sched_yield() c_int; - pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; + pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; }, @@ -227,7 +227,7 @@ pub usingnamespace switch (builtin.os.tag) { pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; pub extern "c" fn sched_yield() c_int; - pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; + pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; diff --git a/lib/std/os.zig b/lib/std/os.zig index e3afe90e5d..b385ffa19f 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4592,7 +4592,7 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { } /// Examine and change a signal action. -pub fn sigaction(sig: u6, act: *const Sigaction, oact: ?*Sigaction) void { +pub fn sigaction(sig: u6, act: ?*const Sigaction, oact: ?*Sigaction) void { switch (errno(system.sigaction(sig, act, oact))) { 0 => return, EFAULT => unreachable, diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 6952ab7e0e..72621b7fee 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -867,13 +867,13 @@ pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffff pub const k_sigaction = if (is_mips) extern struct { flags: usize, - sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, + sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, mask: [4]u32, restorer: fn () callconv(.C) void, } else extern struct { - sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, + sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, flags: usize, restorer: fn () callconv(.C) void, mask: [2]u32, @@ -881,7 +881,7 @@ else /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const sigaction_fn = fn (i32, *siginfo_t, ?*c_void) callconv(.C) void; + pub const sigaction_fn = fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void; sigaction: ?sigaction_fn, mask: sigset_t, flags: u32, diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index b669ed2436..956d92da36 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -857,35 +857,42 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* return syscall4(.rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8); } -pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize { +pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { assert(sig >= 1); assert(sig != SIGKILL); assert(sig != SIGSTOP); - const restorer_fn = if ((act.flags & SA_SIGINFO) != 0) restore_rt else restore; - var ksa = k_sigaction{ - .sigaction = act.sigaction, - .flags = act.flags | SA_RESTORER, - .mask = undefined, - .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), - }; - var ksa_old: k_sigaction = undefined; - const ksa_mask_size = @sizeOf(@TypeOf(ksa_old.mask)); - @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size); + var ksa: k_sigaction = undefined; + var oldksa: k_sigaction = undefined; + const mask_size = @sizeOf(@TypeOf(ksa.mask)); + + if (act) |new| { + const restorer_fn = if ((new.flags & SA_SIGINFO) != 0) restore_rt else restore; + ksa = k_sigaction{ + .sigaction = new.sigaction, + .flags = new.flags | SA_RESTORER, + .mask = undefined, + .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), + }; + @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &new.mask), mask_size); + } + + const ksa_arg = if (act != null) @ptrToInt(&ksa) else 0; + const oldksa_arg = if (oact != null) @ptrToInt(&oldksa) else 0; + const result = switch (builtin.arch) { // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. - .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @ptrToInt(ksa.restorer), ksa_mask_size), - else => syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size), + .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @ptrToInt(ksa.restorer), mask_size), + else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size), }; - const err = getErrno(result); - if (err != 0) { - return result; - } + if (getErrno(result) != 0) return result; + if (oact) |old| { - old.sigaction = ksa_old.sigaction; - old.flags = @truncate(u32, ksa_old.flags); - @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), ksa_mask_size); + old.sigaction = oldksa.sigaction; + old.flags = @truncate(u32, oldksa.flags); + @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &oldksa.mask), mask_size); } + return 0; } diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 81f9922d13..be0c718086 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -646,3 +646,33 @@ test "shutdown socket" { }; os.closeSocket(sock); } + +var signal_test_failed = true; + +test "sigaction" { + if (builtin.os.tag == .wasi or builtin.os.tag == .windows) + return error.SkipZigTest; + + const S = struct { + fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { + // Check that we received the correct signal. + signal_test_failed = info.signo == os.SIGUSR1; + } + }; + + var sa = os.Sigaction{ + .sigaction = S.handler, + .mask = os.empty_sigset, + .flags = os.SA_RESETHAND, + }; + var old_sa: os.Sigaction = undefined; + // Install the new signal handler. + os.sigaction(os.SIGUSR1, &sa, null); + // Check that we can read it back correctly. + os.sigaction(os.SIGUSR1, null, &old_sa); + testing.expectEqual(S.handler, old_sa.sigaction.?); + testing.expect((old_sa.flags & os.SA_RESETHAND) != 0); + // Invoke the handler. + try os.raise(os.SIGUSR1); + testing.expect(signal_test_failed == false); +} From 1d9b28403a1074cbbbd0605f07819136c9f96cdc Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 12 Dec 2020 15:34:26 +0100 Subject: [PATCH 02/10] std: Correct check in signal test Ooops. --- lib/std/os/test.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index be0c718086..6c86f9322f 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -656,14 +656,15 @@ test "sigaction" { const S = struct { fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { // Check that we received the correct signal. - signal_test_failed = info.signo == os.SIGUSR1; + if (sig == os.SIGUSR1 and sig == info.signo) + signal_test_failed = false; } }; var sa = os.Sigaction{ .sigaction = S.handler, .mask = os.empty_sigset, - .flags = os.SA_RESETHAND, + .flags = os.SA_SIGINFO | os.SA_RESETHAND, }; var old_sa: os.Sigaction = undefined; // Install the new signal handler. From 629cc6cf285f60581f03b69ec8d012d2e370a029 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 12 Dec 2020 16:44:10 +0100 Subject: [PATCH 03/10] std: Further siginfo refinements * Define siginfo and sigaction for Darwin * Define sigaction/handler union for maximum libc compatibility * Minor correction to some type definitions --- lib/std/debug.zig | 4 ++-- lib/std/os/bits/darwin.zig | 30 +++++++++++++++++++++---- lib/std/os/bits/dragonfly.zig | 14 +++++++----- lib/std/os/bits/freebsd.zig | 11 ++++++---- lib/std/os/bits/linux.zig | 41 ++++++++++++++++++++++------------- lib/std/os/bits/netbsd.zig | 11 +++++++--- lib/std/os/bits/openbsd.zig | 11 +++++++--- lib/std/os/linux.zig | 6 ++--- lib/std/os/test.zig | 4 ++-- 9 files changed, 91 insertions(+), 41 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 4f0f44d1b7..be5635ee8f 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1721,7 +1721,7 @@ pub fn attachSegfaultHandler() void { return; } var act = os.Sigaction{ - .sigaction = handleSegfaultLinux, + .handler = .{ .sigaction = handleSegfaultLinux }, .mask = os.empty_sigset, .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), }; @@ -1740,7 +1740,7 @@ fn resetSegfaultHandler() void { return; } var act = os.Sigaction{ - .sigaction = os.SIG_DFL, + .handler = .{ .sigaction = os.SIG_DFL }, .mask = os.empty_sigset, .flags = 0, }; diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index 83ca09a9e1..a6dbff8453 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -124,13 +124,35 @@ pub const timespec = extern struct { }; pub const sigset_t = u32; -pub const empty_sigset = sigset_t(0); +pub const empty_sigset: sigset_t = 0; + +pub const siginfo_t = extern struct { + signo: c_int, + errno: c_int, + code: c_int, + pid: pid_t, + uid: uid_t, + status: c_int, + addr: *c_void, + value: extern union { + int: c_int, + ptr: *c_void, + }, + si_band: c_long, + _pad: [7]c_ulong, +}; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. pub const Sigaction = extern struct { - handler: fn (c_int) callconv(.C) void, - sa_mask: sigset_t, - sa_flags: c_int, + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, + }, + mask: sigset_t, + flags: c_uint, }; pub const dirent = extern struct { diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 2fd9e39c7b..61b6b9f363 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -530,12 +530,16 @@ pub const sigset_t = extern struct { }; pub const sig_atomic_t = c_int; pub const Sigaction = extern struct { - __sigaction_u: extern union { - __sa_handler: ?fn (c_int) callconv(.C) void, - __sa_sigaction: ?fn (c_int, [*c]siginfo_t, ?*c_void) callconv(.C) void, + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + + /// signal handler + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, }, - sa_flags: c_int, - sa_mask: sigset_t, + flags: c_uint, + mask: sigset_t, }; pub const sig_t = [*c]fn (c_int) callconv(.C) void; diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index 5dce94bd90..feac7b354a 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -742,14 +742,17 @@ pub const SIG_IGN = @intToPtr(fn (i32) callconv(.C) void, 1); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + /// signal handler - __sigaction_u: extern union { - __sa_handler: fn (i32) callconv(.C) void, - __sa_sigaction: fn (i32, *__siginfo, usize) callconv(.C) void, + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, }, /// see signal options - sa_flags: u32, + sa_flags: c_uint, /// signal mask to apply sa_mask: sigset_t, diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 72621b7fee..e86a08e861 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -864,27 +864,38 @@ pub const sigset_t = [1024 / 32]u32; pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len; pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; -pub const k_sigaction = if (is_mips) - extern struct { - flags: usize, - sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, - mask: [4]u32, +pub const k_sigaction = switch (builtin.arch) { + .mips, .mipsel => extern struct { + flags: c_uint, + handler: ?fn (c_int) callconv(.C) void, + mask: [4]c_ulong, restorer: fn () callconv(.C) void, - } -else - extern struct { - sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, - flags: usize, + }, + .mips64, .mips64el => extern struct { + flags: c_uint, + handler: ?fn (c_int) callconv(.C) void, + mask: [2]c_ulong, restorer: fn () callconv(.C) void, - mask: [2]u32, - }; + }, + else => extern struct { + handler: ?fn (c_int) callconv(.C) void, + flags: c_ulong, + restorer: fn () callconv(.C) void, + mask: [2]c_uint, + }, +}; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const sigaction_fn = fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void; - sigaction: ?sigaction_fn, + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, + }, mask: sigset_t, - flags: u32, + flags: c_uint, restorer: ?fn () callconv(.C) void = null, }; diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index 0f4b6b60fa..316bf3cda2 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -716,13 +716,18 @@ pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const sigaction_fn = fn (i32, *siginfo_t, ?*c_void) callconv(.C) void; + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + /// signal handler - sigaction: ?sigaction_fn, + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, + }, /// signal mask to apply mask: sigset_t, /// signal options - flags: u32, + flags: c_uint, }; pub const sigval_t = extern union { diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index c85a476e02..8b28c0bffd 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -753,13 +753,18 @@ pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const sigaction_fn = fn (c_int, *siginfo_t, ?*c_void) callconv(.C) void; + pub const handler_fn = fn (c_int) callconv(.C) void; + pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void; + /// signal handler - sigaction: ?sigaction_fn, + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, + }, /// signal mask to apply mask: sigset_t, /// signal options - flags: c_int, + flags: c_uint, }; pub const sigval = extern union { diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 956d92da36..f840f6a255 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -869,7 +869,7 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact if (act) |new| { const restorer_fn = if ((new.flags & SA_SIGINFO) != 0) restore_rt else restore; ksa = k_sigaction{ - .sigaction = new.sigaction, + .handler = new.handler.handler, .flags = new.flags | SA_RESTORER, .mask = undefined, .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), @@ -888,8 +888,8 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact if (getErrno(result) != 0) return result; if (oact) |old| { - old.sigaction = oldksa.sigaction; - old.flags = @truncate(u32, oldksa.flags); + old.handler.handler = oldksa.handler; + old.flags = @truncate(c_uint, oldksa.flags); @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &oldksa.mask), mask_size); } diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 6c86f9322f..bbc6c968f1 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -662,7 +662,7 @@ test "sigaction" { }; var sa = os.Sigaction{ - .sigaction = S.handler, + .handler = .{ .sigaction = S.handler }, .mask = os.empty_sigset, .flags = os.SA_SIGINFO | os.SA_RESETHAND, }; @@ -671,7 +671,7 @@ test "sigaction" { os.sigaction(os.SIGUSR1, &sa, null); // Check that we can read it back correctly. os.sigaction(os.SIGUSR1, null, &old_sa); - testing.expectEqual(S.handler, old_sa.sigaction.?); + testing.expectEqual(S.handler, old_sa.handler.sigaction.?); testing.expect((old_sa.flags & os.SA_RESETHAND) != 0); // Invoke the handler. try os.raise(os.SIGUSR1); From fc70db5ab5ab252471cf35acd48dc8dea0b0870d Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 19:17:04 +0100 Subject: [PATCH 04/10] std: Fixes for siginfo test on macos Xnu's sigaction() only supports fetching a limited set of sa_flags, test SA_SIGINFO instead of SA_RESETHAND as that's supported everywhere. Add another check to make sure SA_RESETHAND works. Co-authored-by: Jakub Konka --- lib/std/os/bits/darwin.zig | 5 +++++ lib/std/os/test.zig | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index a6dbff8453..8bd40ed9a3 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -126,6 +126,11 @@ pub const timespec = extern struct { pub const sigset_t = u32; pub const empty_sigset: sigset_t = 0; +pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); +pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); +pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); +pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 5); + pub const siginfo_t = extern struct { signo: c_int, errno: c_int, diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index bbc6c968f1..59116e1bbd 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -672,8 +672,11 @@ test "sigaction" { // Check that we can read it back correctly. os.sigaction(os.SIGUSR1, null, &old_sa); testing.expectEqual(S.handler, old_sa.handler.sigaction.?); - testing.expect((old_sa.flags & os.SA_RESETHAND) != 0); + testing.expect((old_sa.flags & os.SA_SIGINFO) != 0); // Invoke the handler. try os.raise(os.SIGUSR1); testing.expect(signal_test_failed == false); + // Check if the handler has been correctly reset to SIG_DFL + os.sigaction(os.SIGUSR1, null, &old_sa); + testing.expectEqual(os.SIG_DFL, old_sa.handler.sigaction); } From 3375a580be51210115d43b9b76ecf8beef0d46dd Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 19:28:38 +0100 Subject: [PATCH 05/10] std: Update more siginfo bits for BSDs --- lib/std/os/bits/netbsd.zig | 4 ++++ lib/std/os/bits/openbsd.zig | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index 316bf3cda2..be25284b73 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -805,6 +805,10 @@ pub const sigset_t = extern struct { __bits: [_SIG_WORDS]u32, }; +pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); +pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); +pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); + pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS }; // XXX x86_64 specific diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index 8b28c0bffd..9e7b8aa399 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -773,11 +773,6 @@ pub const sigval = extern union { }; pub const siginfo_t = extern union { - pad: [128]u8, - info: _ksiginfo, -}; - -pub const _ksiginfo = extern struct { signo: c_int, code: c_int, errno: c_int, @@ -794,11 +789,22 @@ pub const _ksiginfo = extern struct { addr: ?*c_void, trapno: c_int, }, + __pad: [128 - 3 * @sizeOf(c_int)]u8, } align(@sizeOf(usize)), }; +comptime { + std.debug.assert(@sizeOf(siginfo_t) == 128); +} + pub const sigset_t = c_uint; -pub const empty_sigset = sigset_t(0); +pub const empty_sigset: sigset_t = 0; + +pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); +pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); +pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); +pub const SIG_CATCH = @intToPtr(?Sigaction.sigaction_fn, 2); +pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 3); pub const EPERM = 1; // Operation not permitted pub const ENOENT = 2; // No such file or directory From 3a759fdb17d034cef1699774a098edeff5fc47bc Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 19:34:51 +0100 Subject: [PATCH 06/10] Disable sigaction test on i386 because of #7427 --- lib/std/os/test.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 59116e1bbd..8ad172679b 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -653,6 +653,10 @@ test "sigaction" { if (builtin.os.tag == .wasi or builtin.os.tag == .windows) return error.SkipZigTest; + // https://github.com/ziglang/zig/issues/7427 + if (builtin.os.tag == .linux and builtin.arch == .i386) + return error.SkipZigTest; + const S = struct { fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { // Check that we received the correct signal. From 75159229075a2932beec44d46bf6850d2e585d3c Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Sat, 12 Dec 2020 05:30:06 +0000 Subject: [PATCH 07/10] Fix Sigaction struct on FreeBSD. --- lib/std/os/bits/freebsd.zig | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index feac7b354a..3a71218b37 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -758,6 +758,43 @@ pub const Sigaction = extern struct { sa_mask: sigset_t, }; +pub const __siginfo = extern struct { + si_signo: c_int, + si_errno: c_int, + si_code: c_int, + si_pid: pid_t, + si_uid: uid_t, + si_status: c_int, + si_addr: ?*c_void, + si_value: sigval, + _reason: extern union { + _fault: extern struct { + _trapno: c_int, + }, + _timer: extern struct { + _timerid: c_int, + _overrun: c_int, + }, + _mesgq: extern struct { + _mqd: c_int, + }, + _poll: extern struct { + _band: c_long, + }, + __spare__: extern struct { + __spare1__: c_long, + __spare2__: [7]c_int, + }, + }, +}; + +pub const sigval = extern union { + sival_int: c_int, + sival_ptr: ?*c_void, + sigval_int: c_int, + sigval_ptr: ?*c_void, +}; + pub const _SIG_WORDS = 4; pub const _SIG_MAXSIG = 128; @@ -778,6 +815,8 @@ pub const sigset_t = extern struct { __bits: [_SIG_WORDS]u32, }; +pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS }; + pub const EPERM = 1; // Operation not permitted pub const ENOENT = 2; // No such file or directory pub const ESRCH = 3; // No such process From 97ba3d9a6604a4ac4a92891beb19ec5889bd15ac Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 19:45:11 +0100 Subject: [PATCH 08/10] std: Drop struct prefixes in FreeBSD siginfo I'm not sure this prefix-free style is a good idea, but let's roll with it for the moment. --- lib/std/os/bits/freebsd.zig | 54 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index 3a71218b37..e7cfc2a784 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -752,47 +752,45 @@ pub const Sigaction = extern struct { }, /// see signal options - sa_flags: c_uint, + flags: c_uint, /// signal mask to apply - sa_mask: sigset_t, + mask: sigset_t, }; -pub const __siginfo = extern struct { - si_signo: c_int, - si_errno: c_int, - si_code: c_int, - si_pid: pid_t, - si_uid: uid_t, - si_status: c_int, - si_addr: ?*c_void, - si_value: sigval, - _reason: extern union { - _fault: extern struct { - _trapno: c_int, +pub const siginfo_t = extern struct { + signo: c_int, + errno: c_int, + code: c_int, + pid: pid_t, + uid: uid_t, + status: c_int, + addr: ?*c_void, + value: sigval, + reason: extern union { + fault: extern struct { + trapno: c_int, }, - _timer: extern struct { - _timerid: c_int, - _overrun: c_int, + timer: extern struct { + timerid: c_int, + overrun: c_int, }, - _mesgq: extern struct { - _mqd: c_int, + mesgq: extern struct { + mqd: c_int, }, - _poll: extern struct { - _band: c_long, + poll: extern struct { + band: c_long, }, - __spare__: extern struct { - __spare1__: c_long, - __spare2__: [7]c_int, + spare: extern struct { + spare1: c_long, + spare2: [7]c_int, }, }, }; pub const sigval = extern union { - sival_int: c_int, - sival_ptr: ?*c_void, - sigval_int: c_int, - sigval_ptr: ?*c_void, + int: c_int, + ptr: ?*c_void, }; pub const _SIG_WORDS = 4; From bb72b0e800518863f4bd7fc459fedb7f90d8e9e5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 20:36:34 +0100 Subject: [PATCH 09/10] Fix compilation error on FreeBSD --- lib/std/os/bits/freebsd.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index e7cfc2a784..6378dcaf8d 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -736,9 +736,9 @@ pub const winsize = extern struct { const NSIG = 32; -pub const SIG_ERR = @intToPtr(fn (i32) callconv(.C) void, maxInt(usize)); -pub const SIG_DFL = @intToPtr(fn (i32) callconv(.C) void, 0); -pub const SIG_IGN = @intToPtr(fn (i32) callconv(.C) void, 1); +pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); +pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); +pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { From d9e9390550e8290c1959ad2a8940e94d56f3ae1e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 13 Dec 2020 20:36:47 +0100 Subject: [PATCH 10/10] Fix compilation error on OpenBSD --- lib/std/os/bits/openbsd.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index 9e7b8aa399..5a2d929d03 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -750,6 +750,8 @@ const NSIG = 33; pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); +pub const SIG_CATCH = @intToPtr(?Sigaction.sigaction_fn, 2); +pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 3); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { @@ -772,7 +774,7 @@ pub const sigval = extern union { ptr: ?*c_void, }; -pub const siginfo_t = extern union { +pub const siginfo_t = extern struct { signo: c_int, code: c_int, errno: c_int, @@ -790,22 +792,20 @@ pub const siginfo_t = extern union { trapno: c_int, }, __pad: [128 - 3 * @sizeOf(c_int)]u8, - } align(@sizeOf(usize)), + }, }; comptime { - std.debug.assert(@sizeOf(siginfo_t) == 128); + if (@sizeOf(usize) == 4) + std.debug.assert(@sizeOf(siginfo_t) == 128) + else + // Take into account the padding between errno and data fields. + std.debug.assert(@sizeOf(siginfo_t) == 136); } pub const sigset_t = c_uint; pub const empty_sigset: sigset_t = 0; -pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); -pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0); -pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1); -pub const SIG_CATCH = @intToPtr(?Sigaction.sigaction_fn, 2); -pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 3); - pub const EPERM = 1; // Operation not permitted pub const ENOENT = 2; // No such file or directory pub const ESRCH = 3; // No such process