mirror of
https://github.com/ziglang/zig.git
synced 2026-01-06 21:43:25 +00:00
std: Improve sigaction interface
Add a smoke test to prevent regressions.
This commit is contained in:
parent
d569e37cb5
commit
beae3cea17
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user