123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- #+build linux, darwin, netbsd, openbsd, freebsd
- package posix
- import "core:c"
- when ODIN_OS == .Darwin {
- foreign import lib "system:System.framework"
- } else {
- foreign import lib "system:c"
- }
- // sys/wait.h - declarations for waiting
- foreign lib {
- /*
- Obtains status information pertaining to one of the caller's child processes.
- Returns: -1 (setting errno) on failure or signal on calling process, the pid of the process that caused the return otherwise
- [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html ]]
- */
- wait :: proc(stat_loc: ^c.int) -> pid_t ---
- /*
- Obtains status information pertaining to the given pid specifier.
- If pid is -1, status is requested for any child process.
- If pid is greater than 0, it specifies the process ID of a single child process.
- If pid is 0, it specifies any child process whose process group ID is equal to that of the call.
- If pid is < -1, status is requested for any child whose process group ID is the absolute value of pid.
- Returns: -1 (setting errno) on failure or signal on calling process, 0 if NOHANG and status is not available, the pid of the process that caused the return otherwise
- Example:
- // The following example demonstrates the use of waitpid(), fork(), and the macros used to
- // interpret the status value returned by waitpid() (and wait()). The code segment creates a
- // child process which does some unspecified work. Meanwhile the parent loops performing calls
- // to waitpid() to monitor the status of the child. The loop terminates when child termination
- // is detected.
- child_pid := posix.fork(); switch child_pid {
- case -1: // `fork` failed.
- panic("fork failed")
- case 0: // This is the child.
- // Do some work...
- case:
- for {
- status: i32
- wpid := posix.waitpid(child_pid, &status, { .UNTRACED, .CONTINUED })
- if wpid == -1 {
- panic("waitpid failure")
- }
- switch {
- case posix.WIFEXITED(status):
- fmt.printfln("child exited, status=%v", posix.WEXITSTATUS(status))
- case posix.WIFSIGNALED(status):
- fmt.printfln("child killed (signal %v)", posix.WTERMSIG(status))
- case posix.WIFSTOPPED(status):
- fmt.printfln("child stopped (signal %v", posix.WSTOPSIG(status))
- case posix.WIFCONTINUED(status):
- fmt.println("child continued")
- case:
- // Should never happen.
- fmt.println("unexpected status (%x)", status)
- }
- if posix.WIFEXITED(status) || posix.WIFSIGNALED(status) {
- break
- }
- }
- }
- [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html ]]
- */
- waitpid :: proc(pid: pid_t, stat_loc: ^c.int, options: Wait_Flags) -> pid_t ---
- /*
- Obtains status information pertaining to the given idtype_t and id specifier.
- Returns: 0 if WNOHANG and no status available, 0 if child changed state, -1 (setting errno) on failure
- [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html ]]
- */
- waitid :: proc(idtype: idtype_t, id: id_t, infop: ^siginfo_t, options: Wait_Flags) -> c.int ---
- }
- // If terminated normally.
- WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WIFEXITED(x)
- }
- // If WIFEXITED is true, returns the exit status.
- WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return _WEXITSTATUS(x)
- }
- // If terminated due to an uncaught signal.
- WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WIFSIGNALED(x)
- }
- // If WIFSIGNALED is true, returns the signal.
- WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return _WTERMSIG(x)
- }
- // If status was returned for a child process that is currently stopped.
- WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WIFSTOPPED(x)
- }
- // If WIFSTOPPED, the signal that caused the child process to stop.
- WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return _WSTOPSIG(x)
- }
- // If status was returned for a child process that has continued from a job control stop.
- WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WIFCONTINUED(x)
- }
- idtype_t :: enum c.int {
- // Wait for any children and `id` is ignored.
- P_ALL = _P_ALL,
- // Wait for any child wiith a process group ID equal to `id`.
- P_PID = _P_PID,
- // Wait for any child with a process group ID equal to `id`.
- P_PGID = _P_PGID,
- }
- Wait_Flag_Bits :: enum c.int {
- // Report the status of any continued child process specified by pid whose status has not been
- // reported since it continued from a job control stop.
- CONTINUED = log2(WCONTINUED),
- // Don't suspend execution of the calling thread if status is not immediately available for one
- // of the child processes specified by pid.
- NOHANG = log2(WNOHANG),
- // The status of any child process specified by pid that are stopped, and whose status has not
- // yet been reported since they stopped, shall also be reported to the requesting process.
- UNTRACED = log2(WUNTRACED),
- // Following are only available on `waitid`, not `waitpid`.
- // Wait for processes that have exited.
- EXITED = log2(WEXITED),
- // Keep the process whose status is returned in a waitable state, so it may be waited on again.
- NOWAIT = log2(WNOWAIT),
- // Children that have stopped upon receipt of a signal, and whose status either hasn't been reported
- // or has been reported but that report was called with NOWAIT.
- STOPPED = log2(WSTOPPED),
- }
- Wait_Flags :: bit_set[Wait_Flag_Bits; c.int]
- when ODIN_OS == .Darwin {
- id_t :: distinct c.uint
- WCONTINUED :: 0x00000010
- WNOHANG :: 0x00000001
- WUNTRACED :: 0x00000002
- WEXITED :: 0x00000004
- WNOWAIT :: 0x00000020
- WSTOPPED :: 0x00000008
- _P_ALL :: 0
- _P_PID :: 1
- _P_PGID :: 2
- @(private)
- _WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x & 0o177
- }
- @(private)
- _WSTOPPED :: 0o177
- @(private)
- _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == 0
- }
- @(private)
- _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x >> 8
- }
- @(private)
- _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0
- }
- @(private)
- _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(_WSTATUS(x))
- }
- @(private)
- _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == _WSTOPPED && WSTOPSIG(x) != .SIGCONT
- }
- @(private)
- _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(x >> 8)
- }
- @(private)
- _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == _WSTOPPED && WSTOPSIG(x) == .SIGCONT
- }
- } else when ODIN_OS == .FreeBSD {
- id_t :: distinct c.int64_t
- WCONTINUED :: 4
- WNOHANG :: 1
- WUNTRACED :: 2
- WEXITED :: 16
- WNOWAIT :: 8
- WSTOPPED :: 2
- _P_ALL :: 7
- _P_PID :: 0
- _P_PGID :: 2
- @(private)
- _WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x & 0o177
- }
- @(private)
- _WSTOPPED :: 0o177
- @(private)
- _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == 0
- }
- @(private)
- _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x >> 8
- }
- @(private)
- _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0 && x != c.int(Signal.SIGCONT)
- }
- @(private)
- _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(_WSTATUS(x))
- }
- @(private)
- _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == _WSTOPPED
- }
- @(private)
- _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(x >> 8)
- }
- @(private)
- _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return x == c.int(Signal.SIGCONT)
- }
- } else when ODIN_OS == .NetBSD {
- id_t :: distinct c.uint32_t
- WCONTINUED :: 0x00000010
- WNOHANG :: 0x00000001
- WUNTRACED :: 0x00000002
- WEXITED :: 0x00000020
- WNOWAIT :: 0x00010000
- WSTOPPED :: 0x00000002
- _P_ALL :: 0
- _P_PID :: 1
- _P_PGID :: 2
- @(private)
- _WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x & 0o177
- }
- @(private)
- _WSTOPPED :: 0o177
- @(private)
- _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == 0
- }
- @(private)
- _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return c.int((c.uint(x) >> 8) & 0xff)
- }
- @(private)
- _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return !WIFSTOPPED(x) && !WIFCONTINUED(x) && !WIFEXITED(x)
- }
- @(private)
- _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(_WSTATUS(x))
- }
- @(private)
- _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == _WSTOPPED && !WIFCONTINUED(x)
- }
- @(private)
- _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(c.int((c.uint(x) >> 8) & 0xff))
- }
- @(private)
- _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return x == 0xffff
- }
- } else when ODIN_OS == .OpenBSD {
- id_t :: distinct c.uint32_t
- WCONTINUED :: 0x00000010
- WNOHANG :: 0x00000001
- WUNTRACED :: 0x00000002
- WEXITED :: 0x00000020
- WNOWAIT :: 0x00010000
- WSTOPPED :: 0x00000002
- _P_ALL :: 0
- _P_PID :: 2
- _P_PGID :: 1
- @(private)
- _WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return x & 0o177
- }
- @(private)
- _WSTOPPED :: 0o177
- @(private)
- _WCONTINUED :: 0o177777
- @(private)
- _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) == 0
- }
- @(private)
- _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return (x >> 8) & 0x000000ff
- }
- @(private)
- _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0
- }
- @(private)
- _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(_WSTATUS(x))
- }
- @(private)
- _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return (x & 0xff) == _WSTOPPED
- }
- @(private)
- _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal((x >> 8) & 0xff)
- }
- @(private)
- _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return (x & _WCONTINUED) == _WCONTINUED
- }
- } else when ODIN_OS == .Linux {
- id_t :: distinct c.uint
- WCONTINUED :: 8
- WNOHANG :: 1
- WUNTRACED :: 2
- WEXITED :: 4
- WNOWAIT :: 0x1000000
- WSTOPPED :: 2
- _P_ALL :: 0
- _P_PID :: 1
- _P_PGID :: 2
- @(private)
- _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return _WTERMSIG(x) == nil
- }
- @(private)
- _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
- return (x & 0xff00) >> 8
- }
- @(private)
- _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return (x & 0xffff) - 1 < 0xff
- }
- @(private)
- _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(x & 0x7f)
- }
- @(private)
- _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return ((x & 0xffff) * 0x10001) >> 8 > 0x7f00
- }
- @(private)
- _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
- return Signal(_WEXITSTATUS(x))
- }
- @(private)
- _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
- return x == 0xffff
- }
- }
|