lib/coz/src/signals.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const sys = @import("sys");
3
4 const timer = sys.timer;
5
6 pub const Signal = sys.signal.RawSignal;
7 pub const SignalInfo = sys.signal.SignalInfo;
8 pub const Action = sys.signal.SignalAction;
9 pub const Handler = sys.signal.FaultHandler;
10
11 pub const Installed = struct {
12 signal: Signal,
13 previous: Action,
14 active: bool = true,
15
16 pub fn restore(self: *Installed) void {
17 if (!self.active) return;
18 sys.signal.installAction(self.signal, &self.previous, null) catch {};
19 self.active = false;
20 }
21 };
22
23 pub fn installSampleHandler(handler: Handler) Installed {
24 return install(timer.sample_signal, handler);
25 }
26
27 pub fn install(signal: Signal, handler: Handler) Installed {
28 const act = siginfoAction(handler);
29 var previous: Action = undefined;
30 sys.signal.installAction(signal, &act, &previous) catch return .{
31 .signal = signal,
32 .previous = previous,
33 .active = false,
34 };
35 return .{ .signal = signal, .previous = previous };
36 }
37
38 pub fn siginfoAction(handler: Handler) Action {
39 return sys.signal.siginfoAction(handler);
40 }
41
42 var test_signal_count: std.atomic.Value(u32) = .init(0);
43
44 fn countSignal(_: Signal, _: *const SignalInfo, _: ?*anyopaque) callconv(.c) void {
45 _ = test_signal_count.fetchAdd(1, .monotonic);
46 }
47
48 test "sample signal action uses siginfo handler" {
49 const act = siginfoAction(countSignal);
50 var info: SignalInfo = undefined;
51 test_signal_count.store(0, .monotonic);
52
53 sys.signal.dispatchPreviousAction(act, .USR1, &info, null);
54
55 try std.testing.expectEqual(@as(u32, 1), test_signal_count.load(.monotonic));
56 }
57
58 test "installed signal action dispatches and restores" {
59 test_signal_count.store(0, .monotonic);
60
61 var installed = install(.USR1, countSignal);
62 defer installed.restore();
63
64 sys.signal.raise(.USR1);
65
66 try std.testing.expectEqual(@as(u32, 1), test_signal_count.load(.monotonic));
67 installed.restore();
68 installed.restore();
69 }