signal.ha (3866B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 // XXX: sigwaitinfo and sigtimedwait are not yet available in OpenBSD. Quoting 5 // from OpenBSD's lib/libc/gen/sigwait.c: "need kernel to fill in more siginfo_t 6 // bits first" 7 8 // sigwait 9 10 @symbol("sigwait") fn libc_sigwait(set: *sigset, sig: *int) int; 11 12 export fn sigwait(set: *sigset, sig: *int) (void | errno) = { 13 let res = libc_sigwait(set, sig); 14 if (res != -1) { 15 return *__errno(): errno; 16 }; 17 }; 18 19 export fn alarm(sec: uint) uint = { 20 let nval = itimerval { ... }; 21 let oval = itimerval { ... }; 22 nval.it_value.tv_sec = sec: time_t; 23 setitimer(ITIMER_REAL, &nval, &oval)!; 24 if (oval.it_value.tv_usec != 0) { 25 oval.it_value.tv_sec += 1; 26 }; 27 return oval.it_value.tv_sec: uint; 28 }; 29 30 export def ITIMER_REAL: int = 0; 31 export def ITIMER_VIRTUAL: int = 1; 32 export def ITIMER_PROF: int = 2; 33 34 export type itimerval = struct { 35 it_interval: timeval, 36 it_value: timeval, 37 }; 38 39 // setitimer 40 41 @symbol("setitimer") fn libc_setitimer( 42 which: int, 43 newval: *itimerval, 44 oldval: nullable *itimerval, 45 ) int; 46 47 export fn setitimer( 48 which: int, 49 newval: *itimerval, 50 oldval: nullable *itimerval, 51 ) (void | errno) = { 52 let res = libc_setitimer(which, newval, oldval); 53 if (res != -1) { 54 return *__errno(): errno; 55 }; 56 }; 57 58 // getitimer 59 60 @symbol("getitimer") fn libc_getitimer( 61 which: int, 62 cur: *itimerval, 63 ) int; 64 65 export fn getitimer(which: int, cur: *itimerval) (void | errno) = { 66 let res = libc_getitimer(which, cur); 67 if (res != -1) { 68 return *__errno(): errno; 69 }; 70 }; 71 72 export fn sigemptyset(set: *sigset) void = { 73 *set = 0; 74 }; 75 76 export fn sigaddset(set: *sigset, signum: int) (void | errno) = { 77 if (signum < 1 || signum > NSIG) { 78 return *__errno(): errno; 79 }; 80 *set |= 1u << (signum: uint - 1); 81 }; 82 83 export fn sigdelset(set: *sigset, signum: int) (void | errno) = { 84 if (signum < 1 || signum > NSIG) { 85 return *__errno(): errno; 86 }; 87 *set &= ~(1u << (signum: uint - 1)); 88 }; 89 90 export fn sigismember(set: *sigset, signum: int) (bool | errno) = { 91 if (signum < 1 || signum > NSIG) { 92 return *__errno(): errno; 93 }; 94 return (*set & (1u << (signum: uint - 1))) != 0; 95 }; 96 97 export fn sigfillset(set: *sigset) (void | errno) = { 98 *set = ~0u; 99 }; 100 101 // Test sigset operations do not fail for valid signal numbers. 102 @test fn sigset_valid_signum() void = { 103 let set: sigset = 0; 104 sigemptyset(&set); 105 106 assert(!(sigismember(&set, 1) is errno), "Unexpected error"); 107 assert(!(sigismember(&set, 15) is errno), "Unexpected error"); 108 assert(!(sigismember(&set, NSIG) is errno), "Unexpected error"); 109 110 assert(!(sigaddset(&set, 1) is errno), "Unexpected error"); 111 assert(!(sigaddset(&set, 15) is errno), "Unexpected error"); 112 assert(!(sigaddset(&set, NSIG) is errno), "Unexpected error"); 113 114 // It's ok to add a signal that is already present in the set. 115 assert(!(sigaddset(&set, 1) is errno), "Unexpected error"); 116 117 assert(!(sigdelset(&set, 1) is errno), "Unexpected error"); 118 assert(!(sigdelset(&set, 15) is errno), "Unexpected error"); 119 assert(!(sigdelset(&set, NSIG) is errno), "Unexpected error"); 120 121 // It's ok to delete a signal that is not present in the set. 122 assert(!(sigdelset(&set, 10) is errno), "Unexpected error"); 123 }; 124 125 // Test sigset operations fail for invalid signal numbers. 126 @test fn sigset_invalid_signum() void = { 127 let set: sigset = 0; 128 sigemptyset(&set); 129 130 assert(sigismember(&set, -1) is errno, "Expected error"); 131 assert(sigismember(&set, 0) is errno, "Expected error"); 132 assert(sigismember(&set, NSIG + 1) is errno, "Expected error"); 133 134 assert(sigaddset(&set, -1) is errno, "Expected error"); 135 assert(sigaddset(&set, 0) is errno, "Expected error"); 136 assert(sigaddset(&set, NSIG + 1) is errno, "Expected error"); 137 138 assert(sigdelset(&set, -1) is errno, "Expected error"); 139 assert(sigdelset(&set, 0) is errno, "Expected error"); 140 assert(sigdelset(&set, NSIG + 1) is errno, "Expected error"); 141 };