| author | |
| committer | |
| log | beae3cea178a0a93c25164e992e01c7b5b78e4d7 |
| tree | 71deda4290771d8d710abfbbbc9158016eabc4ea |
| parent | d569e37cb538d17d009f5632c25acd643d3736cb |
Add a smoke test to prevent regressions.5 files changed, 64 insertions(+), 27 deletions(-)
lib/std/c.zig+3-3| ... | ... | @@ -200,7 +200,7 @@ pub usingnamespace switch (builtin.os.tag) { |
| 200 | 200 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 201 | 201 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 202 | 202 | pub extern "c" fn sched_yield() c_int; |
| 203 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 203 | pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 204 | 204 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 205 | 205 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 206 | 206 | 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) { |
| 215 | 215 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 216 | 216 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 217 | 217 | pub extern "c" fn sched_yield() c_int; |
| 218 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 218 | pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 219 | 219 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 220 | 220 | pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; |
| 221 | 221 | }, |
| ... | ... | @@ -227,7 +227,7 @@ pub usingnamespace switch (builtin.os.tag) { |
| 227 | 227 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 228 | 228 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 229 | 229 | pub extern "c" fn sched_yield() c_int; |
| 230 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 230 | pub extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int; | |
| 231 | 231 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 232 | 232 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 233 | 233 | pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; |
lib/std/os.zig+1-1| ... | ... | @@ -4592,7 +4592,7 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { |
| 4592 | 4592 | } |
| 4593 | 4593 | |
| 4594 | 4594 | /// Examine and change a signal action. |
| 4595 | pub fn sigaction(sig: u6, act: *const Sigaction, oact: ?*Sigaction) void { | |
| 4595 | pub fn sigaction(sig: u6, act: ?*const Sigaction, oact: ?*Sigaction) void { | |
| 4596 | 4596 | switch (errno(system.sigaction(sig, act, oact))) { |
| 4597 | 4597 | 0 => return, |
| 4598 | 4598 | EFAULT => unreachable, |
lib/std/os/bits/linux.zig+3-3| ... | ... | @@ -867,13 +867,13 @@ pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffff |
| 867 | 867 | pub const k_sigaction = if (is_mips) |
| 868 | 868 | extern struct { |
| 869 | 869 | flags: usize, |
| 870 | sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, | |
| 870 | sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, | |
| 871 | 871 | mask: [4]u32, |
| 872 | 872 | restorer: fn () callconv(.C) void, |
| 873 | 873 | } |
| 874 | 874 | else |
| 875 | 875 | extern struct { |
| 876 | sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, | |
| 876 | sigaction: ?fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void, | |
| 877 | 877 | flags: usize, |
| 878 | 878 | restorer: fn () callconv(.C) void, |
| 879 | 879 | mask: [2]u32, |
| ... | ... | @@ -881,7 +881,7 @@ else |
| 881 | 881 | |
| 882 | 882 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 883 | 883 | pub const Sigaction = extern struct { |
| 884 | pub const sigaction_fn = fn (i32, *siginfo_t, ?*c_void) callconv(.C) void; | |
| 884 | pub const sigaction_fn = fn (i32, *const siginfo_t, ?*const c_void) callconv(.C) void; | |
| 885 | 885 | sigaction: ?sigaction_fn, |
| 886 | 886 | mask: sigset_t, |
| 887 | 887 | flags: u32, |
lib/std/os/linux.zig+27-20| ... | ... | @@ -857,35 +857,42 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* |
| 857 | 857 | return syscall4(.rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8); |
| 858 | 858 | } |
| 859 | 859 | |
| 860 | pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize { | |
| 860 | pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { | |
| 861 | 861 | assert(sig >= 1); |
| 862 | 862 | assert(sig != SIGKILL); |
| 863 | 863 | assert(sig != SIGSTOP); |
| 864 | 864 | |
| 865 | const restorer_fn = if ((act.flags & SA_SIGINFO) != 0) restore_rt else restore; | |
| 866 | var ksa = k_sigaction{ | |
| 867 | .sigaction = act.sigaction, | |
| 868 | .flags = act.flags | SA_RESTORER, | |
| 869 | .mask = undefined, | |
| 870 | .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), | |
| 871 | }; | |
| 872 | var ksa_old: k_sigaction = undefined; | |
| 873 | const ksa_mask_size = @sizeOf(@TypeOf(ksa_old.mask)); | |
| 874 | @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size); | |
| 865 | var ksa: k_sigaction = undefined; | |
| 866 | var oldksa: k_sigaction = undefined; | |
| 867 | const mask_size = @sizeOf(@TypeOf(ksa.mask)); | |
| 868 | ||
| 869 | if (act) |new| { | |
| 870 | const restorer_fn = if ((new.flags & SA_SIGINFO) != 0) restore_rt else restore; | |
| 871 | ksa = k_sigaction{ | |
| 872 | .sigaction = new.sigaction, | |
| 873 | .flags = new.flags | SA_RESTORER, | |
| 874 | .mask = undefined, | |
| 875 | .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), | |
| 876 | }; | |
| 877 | @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &new.mask), mask_size); | |
| 878 | } | |
| 879 | ||
| 880 | const ksa_arg = if (act != null) @ptrToInt(&ksa) else 0; | |
| 881 | const oldksa_arg = if (oact != null) @ptrToInt(&oldksa) else 0; | |
| 882 | ||
| 875 | 883 | const result = switch (builtin.arch) { |
| 876 | 884 | // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. |
| 877 | .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @ptrToInt(ksa.restorer), ksa_mask_size), | |
| 878 | else => syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size), | |
| 885 | .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @ptrToInt(ksa.restorer), mask_size), | |
| 886 | else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size), | |
| 879 | 887 | }; |
| 880 | const err = getErrno(result); | |
| 881 | if (err != 0) { | |
| 882 | return result; | |
| 883 | } | |
| 888 | if (getErrno(result) != 0) return result; | |
| 889 | ||
| 884 | 890 | if (oact) |old| { |
| 885 | old.sigaction = ksa_old.sigaction; | |
| 886 | old.flags = @truncate(u32, ksa_old.flags); | |
| 887 | @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), ksa_mask_size); | |
| 891 | old.sigaction = oldksa.sigaction; | |
| 892 | old.flags = @truncate(u32, oldksa.flags); | |
| 893 | @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &oldksa.mask), mask_size); | |
| 888 | 894 | } |
| 895 | ||
| 889 | 896 | return 0; |
| 890 | 897 | } |
| 891 | 898 |
lib/std/os/test.zig+30| ... | ... | @@ -646,3 +646,33 @@ test "shutdown socket" { |
| 646 | 646 | }; |
| 647 | 647 | os.closeSocket(sock); |
| 648 | 648 | } |
| 649 | ||
| 650 | var signal_test_failed = true; | |
| 651 | ||
| 652 | test "sigaction" { | |
| 653 | if (builtin.os.tag == .wasi or builtin.os.tag == .windows) | |
| 654 | return error.SkipZigTest; | |
| 655 | ||
| 656 | const S = struct { | |
| 657 | fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { | |
| 658 | // Check that we received the correct signal. | |
| 659 | signal_test_failed = info.signo == os.SIGUSR1; | |
| 660 | } | |
| 661 | }; | |
| 662 | ||
| 663 | var sa = os.Sigaction{ | |
| 664 | .sigaction = S.handler, | |
| 665 | .mask = os.empty_sigset, | |
| 666 | .flags = os.SA_RESETHAND, | |
| 667 | }; | |
| 668 | var old_sa: os.Sigaction = undefined; | |
| 669 | // Install the new signal handler. | |
| 670 | os.sigaction(os.SIGUSR1, &sa, null); | |
| 671 | // Check that we can read it back correctly. | |
| 672 | os.sigaction(os.SIGUSR1, null, &old_sa); | |
| 673 | testing.expectEqual(S.handler, old_sa.sigaction.?); | |
| 674 | testing.expect((old_sa.flags & os.SA_RESETHAND) != 0); | |
| 675 | // Invoke the handler. | |
| 676 | try os.raise(os.SIGUSR1); | |
| 677 | testing.expect(signal_test_failed == false); | |
| 678 | } |