signal.ha (3996B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 // TODO: work when _NSIG != 32 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 = sigwaitinfo(set, null)?; 46 }; 47 48 export fn sigwaitinfo( 49 set: *sigset, 50 info: nullable *siginfo, 51 ) (int | errno) = { 52 return wrap_return(syscall2(SYS_sigwaitinfo, 53 set: uintptr: u64, 54 info: uintptr: u64, 55 ))?: int; 56 }; 57 58 export fn sigtimedwait( 59 set: *sigset, 60 info: nullable *siginfo, 61 timeout: nullable *timespec, 62 ) (int | errno) = { 63 return wrap_return(syscall3(SYS_sigtimedwait, 64 set: uintptr: u64, 65 info: uintptr: u64, 66 timeout: uintptr: u64, 67 ))?: int; 68 }; 69 70 export fn sigemptyset(set: *sigset) void = { 71 for (let i = 0z; i < len(set.__bits); i += 1) { 72 set.__bits[i] = 0; 73 }; 74 }; 75 76 export fn sigaddset(set: *sigset, signum: int) (void | errno) = { 77 if (signum < 1 || signum > NSIG) { 78 return EINVAL; 79 }; 80 signum -= 1; 81 set.__bits[signum >> 5] |= (1 << signum): u32; 82 }; 83 84 export fn sigdelset(set: *sigset, signum: int) (void | errno) = { 85 if (signum < 1 || signum > NSIG) { 86 return EINVAL; 87 }; 88 signum -= 1; 89 set.__bits[signum >> 5] &= ~(1 << signum: u32); 90 }; 91 92 export fn sigismember(set: *sigset, signum: int) (bool | errno) = { 93 if (signum < 1 || signum > NSIG) { 94 return EINVAL; 95 }; 96 signum -= 1; 97 return (set.__bits[signum >> 5] & (1 << signum: u32)) != 0; 98 }; 99 100 export fn sigfillset(set: *sigset) (void | errno) = { 101 for (let i = 0z; i < len(set.__bits); i += 1) { 102 set.__bits[i] = ~0u32; 103 }; 104 }; 105 106 // Test sigset operations do not fail for valid signal numbers. 107 @test fn sigset_valid_signum() void = { 108 let set: sigset = sigset { ... }; 109 sigemptyset(&set); 110 111 assert(!(sigismember(&set, 1) is errno), "Unexpected error"); 112 assert(!(sigismember(&set, 15) is errno), "Unexpected error"); 113 assert(!(sigismember(&set, NSIG) is errno), "Unexpected error"); 114 115 assert(!(sigaddset(&set, 1) is errno), "Unexpected error"); 116 assert(!(sigaddset(&set, 15) is errno), "Unexpected error"); 117 assert(!(sigaddset(&set, NSIG) is errno), "Unexpected error"); 118 119 // It's ok to add a signal that is already present in the set. 120 assert(!(sigaddset(&set, 1) is errno), "Unexpected error"); 121 122 assert(!(sigdelset(&set, 1) is errno), "Unexpected error"); 123 assert(!(sigdelset(&set, 15) is errno), "Unexpected error"); 124 assert(!(sigdelset(&set, NSIG) is errno), "Unexpected error"); 125 126 // It's ok to delete a signal that is not present in the set. 127 assert(!(sigdelset(&set, 10) is errno), "Unexpected error"); 128 }; 129 130 // Test sigset operations fail for invalid signal numbers. 131 @test fn sigset_invalid_signum() void = { 132 let set: sigset = sigset { ... }; 133 sigemptyset(&set); 134 135 assert(sigismember(&set, -1) is errno, "Expected error"); 136 assert(sigismember(&set, 0) is errno, "Expected error"); 137 assert(sigismember(&set, NSIG + 1) is errno, "Expected error"); 138 139 assert(sigaddset(&set, -1) is errno, "Expected error"); 140 assert(sigaddset(&set, 0) is errno, "Expected error"); 141 assert(sigaddset(&set, NSIG + 1) is errno, "Expected error"); 142 143 assert(sigdelset(&set, -1) is errno, "Expected error"); 144 assert(sigdelset(&set, 0) is errno, "Expected error"); 145 assert(sigdelset(&set, NSIG + 1) is errno, "Expected error"); 146 };