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 }