| 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,7 +200,7 @@ pub usingnamespace switch (builtin.os.tag) { |
| 200 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 200 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 201 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 201 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 202 | pub extern "c" fn sched_yield() c_int; | 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 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; | 204 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 205 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; | 205 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 206 | pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; | 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,7 +215,7 @@ pub usingnamespace switch (builtin.os.tag) { |
| 215 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 215 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 216 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 216 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 217 | pub extern "c" fn sched_yield() c_int; | 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 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; | 219 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 220 | pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; | 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,7 +227,7 @@ pub usingnamespace switch (builtin.os.tag) { |
| 227 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 227 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 228 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 228 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 229 | pub extern "c" fn sched_yield() c_int; | 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 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; | 231 | pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 232 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; | 232 | pub extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 233 | pub extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *libc_stat) c_int; | 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,7 +4592,7 @@ pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void { |
| 4592 | } | 4592 | } |
| 4593 | 4593 | ||
| 4594 | /// Examine and change a signal action. | 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 | switch (errno(system.sigaction(sig, act, oact))) { | 4596 | switch (errno(system.sigaction(sig, act, oact))) { |
| 4597 | 0 => return, | 4597 | 0 => return, |
| 4598 | EFAULT => unreachable, | 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,13 +867,13 @@ pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffff |
| 867 | pub const k_sigaction = if (is_mips) | 867 | pub const k_sigaction = if (is_mips) |
| 868 | extern struct { | 868 | extern struct { |
| 869 | flags: usize, | 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 | mask: [4]u32, | 871 | mask: [4]u32, |
| 872 | restorer: fn () callconv(.C) void, | 872 | restorer: fn () callconv(.C) void, |
| 873 | } | 873 | } |
| 874 | else | 874 | else |
| 875 | extern struct { | 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 | flags: usize, | 877 | flags: usize, |
| 878 | restorer: fn () callconv(.C) void, | 878 | restorer: fn () callconv(.C) void, |
| 879 | mask: [2]u32, | 879 | mask: [2]u32, |
| ... | @@ -881,7 +881,7 @@ else | ... | @@ -881,7 +881,7 @@ else |
| 881 | 881 | ||
| 882 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 882 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 883 | pub const Sigaction = extern struct { | 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 | sigaction: ?sigaction_fn, | 885 | sigaction: ?sigaction_fn, |
| 886 | mask: sigset_t, | 886 | mask: sigset_t, |
| 887 | flags: u32, | 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,35 +857,42 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* |
| 857 | return syscall4(.rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8); | 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 | assert(sig >= 1); | 861 | assert(sig >= 1); |
| 862 | assert(sig != SIGKILL); | 862 | assert(sig != SIGKILL); |
| 863 | assert(sig != SIGSTOP); | 863 | assert(sig != SIGSTOP); |
| 864 | 864 | ||
| 865 | const restorer_fn = if ((act.flags & SA_SIGINFO) != 0) restore_rt else restore; | 865 | var ksa: k_sigaction = undefined; |
| 866 | var ksa = k_sigaction{ | 866 | var oldksa: k_sigaction = undefined; |
| 867 | .sigaction = act.sigaction, | 867 | const mask_size = @sizeOf(@TypeOf(ksa.mask)); |
| 868 | .flags = act.flags | SA_RESTORER, | 868 | |
| 869 | .mask = undefined, | 869 | if (act) |new| { |
| 870 | .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), | 870 | const restorer_fn = if ((new.flags & SA_SIGINFO) != 0) restore_rt else restore; |
| 871 | }; | 871 | ksa = k_sigaction{ |
| 872 | var ksa_old: k_sigaction = undefined; | 872 | .sigaction = new.sigaction, |
| 873 | const ksa_mask_size = @sizeOf(@TypeOf(ksa_old.mask)); | 873 | .flags = new.flags | SA_RESTORER, |
| 874 | @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size); | 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 | const result = switch (builtin.arch) { | 883 | const result = switch (builtin.arch) { |
| 876 | // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. | 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), | 885 | .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @ptrToInt(ksa.restorer), mask_size), |
| 878 | else => syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size), | 886 | else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size), |
| 879 | }; | 887 | }; |
| 880 | const err = getErrno(result); | 888 | if (getErrno(result) != 0) return result; |
| 881 | if (err != 0) { | 889 | |
| 882 | return result; | ||
| 883 | } | ||
| 884 | if (oact) |old| { | 890 | if (oact) |old| { |
| 885 | old.sigaction = ksa_old.sigaction; | 891 | old.sigaction = oldksa.sigaction; |
| 886 | old.flags = @truncate(u32, ksa_old.flags); | 892 | old.flags = @truncate(u32, oldksa.flags); |
| 887 | @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), ksa_mask_size); | 893 | @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &oldksa.mask), mask_size); |
| 888 | } | 894 | } |
| 895 | |||
| 889 | return 0; | 896 | return 0; |
| 890 | } | 897 | } |
| 891 | 898 |
lib/std/os/test.zig+30| ... | @@ -646,3 +646,33 @@ test "shutdown socket" { | ... | @@ -646,3 +646,33 @@ test "shutdown socket" { |
| 646 | }; | 646 | }; |
| 647 | os.closeSocket(sock); | 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 | } |