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