authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-14 17:16:55+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-12-14 17:16:55+01:00
log91e8be385cdcc53bb8703f317e6f1f7fd4239e4f
tree15ea052a2567d9eb9acd8bc3c778bacc9522830f
parenta471a57560401c5562c4dc3e588227b689bf9487
parentd9e9390550e8290c1959ad2a8940e94d56f3ae1e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7411 from LemonBoy/sigaction-smoke

std: Improve sigaction interface

11 files changed, 219 insertions(+), 72 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/debug.zig+2-2
...@@ -1721,7 +1721,7 @@ pub fn attachSegfaultHandler() void {...@@ -1721,7 +1721,7 @@ pub fn attachSegfaultHandler() void {
1721 return;1721 return;
1722 }1722 }
1723 var act = os.Sigaction{1723 var act = os.Sigaction{
1724 .sigaction = handleSegfaultLinux,1724 .handler = .{ .sigaction = handleSegfaultLinux },
1725 .mask = os.empty_sigset,1725 .mask = os.empty_sigset,
1726 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),1726 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
1727 };1727 };
...@@ -1740,7 +1740,7 @@ fn resetSegfaultHandler() void {...@@ -1740,7 +1740,7 @@ fn resetSegfaultHandler() void {
1740 return;1740 return;
1741 }1741 }
1742 var act = os.Sigaction{1742 var act = os.Sigaction{
1743 .sigaction = os.SIG_DFL,1743 .handler = .{ .sigaction = os.SIG_DFL },
1744 .mask = os.empty_sigset,1744 .mask = os.empty_sigset,
1745 .flags = 0,1745 .flags = 0,
1746 };1746 };
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}
45934593
4594/// Examine and change a signal action.4594/// Examine and change a signal action.
4595pub fn sigaction(sig: u6, act: *const Sigaction, oact: ?*Sigaction) void {4595pub 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/darwin.zig+31-4
...@@ -124,13 +124,40 @@ pub const timespec = extern struct {...@@ -124,13 +124,40 @@ pub const timespec = extern struct {
124};124};
125125
126pub const sigset_t = u32;126pub const sigset_t = u32;
127pub const empty_sigset = sigset_t(0);127pub const empty_sigset: sigset_t = 0;
128
129pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
130pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
131pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
132pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 5);
133
134pub const siginfo_t = extern struct {
135 signo: c_int,
136 errno: c_int,
137 code: c_int,
138 pid: pid_t,
139 uid: uid_t,
140 status: c_int,
141 addr: *c_void,
142 value: extern union {
143 int: c_int,
144 ptr: *c_void,
145 },
146 si_band: c_long,
147 _pad: [7]c_ulong,
148};
128149
129/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.150/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
130pub const Sigaction = extern struct {151pub const Sigaction = extern struct {
131 handler: fn (c_int) callconv(.C) void,152 pub const handler_fn = fn (c_int) callconv(.C) void;
132 sa_mask: sigset_t,153 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
133 sa_flags: c_int,154
155 handler: extern union {
156 handler: ?handler_fn,
157 sigaction: ?sigaction_fn,
158 },
159 mask: sigset_t,
160 flags: c_uint,
134};161};
135162
136pub const dirent = extern struct {163pub const dirent = extern struct {
lib/std/os/bits/dragonfly.zig+9-5
...@@ -530,12 +530,16 @@ pub const sigset_t = extern struct {...@@ -530,12 +530,16 @@ pub const sigset_t = extern struct {
530};530};
531pub const sig_atomic_t = c_int;531pub const sig_atomic_t = c_int;
532pub const Sigaction = extern struct {532pub const Sigaction = extern struct {
533 __sigaction_u: extern union {533 pub const handler_fn = fn (c_int) callconv(.C) void;
534 __sa_handler: ?fn (c_int) callconv(.C) void,534 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
535 __sa_sigaction: ?fn (c_int, [*c]siginfo_t, ?*c_void) callconv(.C) void,535
536 /// signal handler
537 handler: extern union {
538 handler: ?handler_fn,
539 sigaction: ?sigaction_fn,
536 },540 },
537 sa_flags: c_int,541 flags: c_uint,
538 sa_mask: sigset_t,542 mask: sigset_t,
539};543};
540pub const sig_t = [*c]fn (c_int) callconv(.C) void;544pub const sig_t = [*c]fn (c_int) callconv(.C) void;
541545
lib/std/os/bits/freebsd.zig+48-8
...@@ -736,23 +736,61 @@ pub const winsize = extern struct {...@@ -736,23 +736,61 @@ pub const winsize = extern struct {
736736
737const NSIG = 32;737const NSIG = 32;
738738
739pub const SIG_ERR = @intToPtr(fn (i32) callconv(.C) void, maxInt(usize));739pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
740pub const SIG_DFL = @intToPtr(fn (i32) callconv(.C) void, 0);740pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
741pub const SIG_IGN = @intToPtr(fn (i32) callconv(.C) void, 1);741pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
742742
743/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.743/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
744pub const Sigaction = extern struct {744pub const Sigaction = extern struct {
745 pub const handler_fn = fn (c_int) callconv(.C) void;
746 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
747
745 /// signal handler748 /// signal handler
746 __sigaction_u: extern union {749 handler: extern union {
747 __sa_handler: fn (i32) callconv(.C) void,750 handler: ?handler_fn,
748 __sa_sigaction: fn (i32, *__siginfo, usize) callconv(.C) void,751 sigaction: ?sigaction_fn,
749 },752 },
750753
751 /// see signal options754 /// see signal options
752 sa_flags: u32,755 flags: c_uint,
753756
754 /// signal mask to apply757 /// signal mask to apply
755 sa_mask: sigset_t,758 mask: sigset_t,
759};
760
761pub const siginfo_t = extern struct {
762 signo: c_int,
763 errno: c_int,
764 code: c_int,
765 pid: pid_t,
766 uid: uid_t,
767 status: c_int,
768 addr: ?*c_void,
769 value: sigval,
770 reason: extern union {
771 fault: extern struct {
772 trapno: c_int,
773 },
774 timer: extern struct {
775 timerid: c_int,
776 overrun: c_int,
777 },
778 mesgq: extern struct {
779 mqd: c_int,
780 },
781 poll: extern struct {
782 band: c_long,
783 },
784 spare: extern struct {
785 spare1: c_long,
786 spare2: [7]c_int,
787 },
788 },
789};
790
791pub const sigval = extern union {
792 int: c_int,
793 ptr: ?*c_void,
756};794};
757795
758pub const _SIG_WORDS = 4;796pub const _SIG_WORDS = 4;
...@@ -775,6 +813,8 @@ pub const sigset_t = extern struct {...@@ -775,6 +813,8 @@ pub const sigset_t = extern struct {
775 __bits: [_SIG_WORDS]u32,813 __bits: [_SIG_WORDS]u32,
776};814};
777815
816pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };
817
778pub const EPERM = 1; // Operation not permitted818pub const EPERM = 1; // Operation not permitted
779pub const ENOENT = 2; // No such file or directory819pub const ENOENT = 2; // No such file or directory
780pub const ESRCH = 3; // No such process820pub const ESRCH = 3; // No such process
lib/std/os/bits/linux.zig+26-15
...@@ -864,27 +864,38 @@ pub const sigset_t = [1024 / 32]u32;...@@ -864,27 +864,38 @@ pub const sigset_t = [1024 / 32]u32;
864pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;864pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;
865pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;865pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
866866
867pub const k_sigaction = if (is_mips)867pub const k_sigaction = switch (builtin.arch) {
868 extern struct {868 .mips, .mipsel => extern struct {
869 flags: usize,869 flags: c_uint,
870 sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void,870 handler: ?fn (c_int) callconv(.C) void,
871 mask: [4]u32,871 mask: [4]c_ulong,
872 restorer: fn () callconv(.C) void,872 restorer: fn () callconv(.C) void,
873 }873 },
874else874 .mips64, .mips64el => extern struct {
875 extern struct {875 flags: c_uint,
876 sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void,876 handler: ?fn (c_int) callconv(.C) void,
877 flags: usize,877 mask: [2]c_ulong,
878 restorer: fn () callconv(.C) void,878 restorer: fn () callconv(.C) void,
879 mask: [2]u32,879 },
880 };880 else => extern struct {
881 handler: ?fn (c_int) callconv(.C) void,
882 flags: c_ulong,
883 restorer: fn () callconv(.C) void,
884 mask: [2]c_uint,
885 },
886};
881887
882/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.888/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
883pub const Sigaction = extern struct {889pub const Sigaction = extern struct {
884 pub const sigaction_fn = fn (i32, *siginfo_t, ?*c_void) callconv(.C) void;890 pub const handler_fn = fn (c_int) callconv(.C) void;
885 sigaction: ?sigaction_fn,891 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
892
893 handler: extern union {
894 handler: ?handler_fn,
895 sigaction: ?sigaction_fn,
896 },
886 mask: sigset_t,897 mask: sigset_t,
887 flags: u32,898 flags: c_uint,
888 restorer: ?fn () callconv(.C) void = null,899 restorer: ?fn () callconv(.C) void = null,
889};900};
890901
lib/std/os/bits/netbsd.zig+12-3
...@@ -716,13 +716,18 @@ pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);...@@ -716,13 +716,18 @@ pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
716716
717/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.717/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
718pub const Sigaction = extern struct {718pub const Sigaction = extern struct {
719 pub const sigaction_fn = fn (i32, *siginfo_t, ?*c_void) callconv(.C) void;719 pub const handler_fn = fn (c_int) callconv(.C) void;
720 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
721
720 /// signal handler722 /// signal handler
721 sigaction: ?sigaction_fn,723 handler: extern union {
724 handler: ?handler_fn,
725 sigaction: ?sigaction_fn,
726 },
722 /// signal mask to apply727 /// signal mask to apply
723 mask: sigset_t,728 mask: sigset_t,
724 /// signal options729 /// signal options
725 flags: u32,730 flags: c_uint,
726};731};
727732
728pub const sigval_t = extern union {733pub const sigval_t = extern union {
...@@ -800,6 +805,10 @@ pub const sigset_t = extern struct {...@@ -800,6 +805,10 @@ pub const sigset_t = extern struct {
800 __bits: [_SIG_WORDS]u32,805 __bits: [_SIG_WORDS]u32,
801};806};
802807
808pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
809pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
810pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
811
803pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };812pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };
804813
805// XXX x86_64 specific814// XXX x86_64 specific
lib/std/os/bits/openbsd.zig+22-11
...@@ -750,16 +750,23 @@ const NSIG = 33;...@@ -750,16 +750,23 @@ const NSIG = 33;
750pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));750pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
751pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);751pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
752pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);752pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
753pub const SIG_CATCH = @intToPtr(?Sigaction.sigaction_fn, 2);
754pub const SIG_HOLD = @intToPtr(?Sigaction.sigaction_fn, 3);
753755
754/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.756/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
755pub const Sigaction = extern struct {757pub const Sigaction = extern struct {
756 pub const sigaction_fn = fn (c_int, *siginfo_t, ?*c_void) callconv(.C) void;758 pub const handler_fn = fn (c_int) callconv(.C) void;
759 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
760
757 /// signal handler761 /// signal handler
758 sigaction: ?sigaction_fn,762 handler: extern union {
763 handler: ?handler_fn,
764 sigaction: ?sigaction_fn,
765 },
759 /// signal mask to apply766 /// signal mask to apply
760 mask: sigset_t,767 mask: sigset_t,
761 /// signal options768 /// signal options
762 flags: c_int,769 flags: c_uint,
763};770};
764771
765pub const sigval = extern union {772pub const sigval = extern union {
...@@ -767,12 +774,7 @@ pub const sigval = extern union {...@@ -767,12 +774,7 @@ pub const sigval = extern union {
767 ptr: ?*c_void,774 ptr: ?*c_void,
768};775};
769776
770pub const siginfo_t = extern union {777pub const siginfo_t = extern struct {
771 pad: [128]u8,
772 info: _ksiginfo,
773};
774
775pub const _ksiginfo = extern struct {
776 signo: c_int,778 signo: c_int,
777 code: c_int,779 code: c_int,
778 errno: c_int,780 errno: c_int,
...@@ -789,11 +791,20 @@ pub const _ksiginfo = extern struct {...@@ -789,11 +791,20 @@ pub const _ksiginfo = extern struct {
789 addr: ?*c_void,791 addr: ?*c_void,
790 trapno: c_int,792 trapno: c_int,
791 },793 },
792 } align(@sizeOf(usize)),794 __pad: [128 - 3 * @sizeOf(c_int)]u8,
795 },
793};796};
794797
798comptime {
799 if (@sizeOf(usize) == 4)
800 std.debug.assert(@sizeOf(siginfo_t) == 128)
801 else
802 // Take into account the padding between errno and data fields.
803 std.debug.assert(@sizeOf(siginfo_t) == 136);
804}
805
795pub const sigset_t = c_uint;806pub const sigset_t = c_uint;
796pub const empty_sigset = sigset_t(0);807pub const empty_sigset: sigset_t = 0;
797808
798pub const EPERM = 1; // Operation not permitted809pub const EPERM = 1; // Operation not permitted
799pub const ENOENT = 2; // No such file or directory810pub const ENOENT = 2; // No such file or directory
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}
859859
860pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {860pub 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);
864864
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 .handler = new.handler.handler,
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.handler.handler = oldksa.handler;
886 old.flags = @truncate(u32, ksa_old.flags);892 old.flags = @truncate(c_uint, 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}
891898
lib/std/os/test.zig+38
...@@ -646,3 +646,41 @@ test "shutdown socket" {...@@ -646,3 +646,41 @@ test "shutdown socket" {
646 };646 };
647 os.closeSocket(sock);647 os.closeSocket(sock);
648}648}
649
650var signal_test_failed = true;
651
652test "sigaction" {
653 if (builtin.os.tag == .wasi or builtin.os.tag == .windows)
654 return error.SkipZigTest;
655
656 // https://github.com/ziglang/zig/issues/7427
657 if (builtin.os.tag == .linux and builtin.arch == .i386)
658 return error.SkipZigTest;
659
660 const S = struct {
661 fn handler(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void {
662 // Check that we received the correct signal.
663 if (sig == os.SIGUSR1 and sig == info.signo)
664 signal_test_failed = false;
665 }
666 };
667
668 var sa = os.Sigaction{
669 .handler = .{ .sigaction = S.handler },
670 .mask = os.empty_sigset,
671 .flags = os.SA_SIGINFO | os.SA_RESETHAND,
672 };
673 var old_sa: os.Sigaction = undefined;
674 // Install the new signal handler.
675 os.sigaction(os.SIGUSR1, &sa, null);
676 // Check that we can read it back correctly.
677 os.sigaction(os.SIGUSR1, null, &old_sa);
678 testing.expectEqual(S.handler, old_sa.handler.sigaction.?);
679 testing.expect((old_sa.flags & os.SA_SIGINFO) != 0);
680 // Invoke the handler.
681 try os.raise(os.SIGUSR1);
682 testing.expect(signal_test_failed == false);
683 // Check if the handler has been correctly reset to SIG_DFL
684 os.sigaction(os.SIGUSR1, null, &old_sa);
685 testing.expectEqual(os.SIG_DFL, old_sa.handler.sigaction);
686}