#ifndef VLIBC_SYS_WAIT_H #define VLIBC_SYS_WAIT_H /* * vlibc — . * * Child-process status collection (POSIX.1-2008) and the wait status macros. * Everything here is a pass-through to the kernel: wait/waitpid/wait3/wait4 * ride SYS_wait4, waitid rides SYS_waitid, and failures are reported as -1 * (or the child pid on success) with errno set by the syscall layer. * * Level 1 (onlyposix): wait, waitpid, waitid + the W* status macros. * Level 2 (muslmimic): wait3, wait4 (XSI). * * The W* decode macros follow the kernel's wait status encoding: bits 0-6 * hold the terminating signal (or 0x7f for a stop), bit 7 the core-dump * flag, bits 8-15 the exit status, and the word 0xffff marks a continued * child. WEXITED/WSTOPPED/WNOWAIT are the waitid-only option bits (XSI; * kernel-identical values) and WCOREDUMP is an XSI/Linux extension (bit * 0x80) kept alongside the POSIX set for source compatibility. * * None of the declarations carry an intent attribute: every function has * kernel-visible side effects and reports failures through errno. * * does not exist yet (a later todo owns it). The minimal * siginfo_t below and the CLD_* constants live here under guards so that * header can take them over without conflict; see the notes by each. */ #include #include #ifdef __cplusplus extern "C" { #endif /* * Selector type for waitid(). POSIX defines idtype_t as an integer type and * places it in , which does not define it yet; it is provided * here under a VLIBC_ guard so sys/types.h can take it over later without a * redefinition. int matches the kernel's `which` argument on x86_64. */ #ifndef VLIBC_DEFINED_IDTYPE_T #define VLIBC_DEFINED_IDTYPE_T typedef int idtype_t; #endif /* waitid() idtype selectors (kernel-identical). */ #define P_ALL 0 /* wait for any child */ #define P_PID 1 /* wait for the specific child */ #define P_PGID 2 /* wait for any child in the process group */ /* wait/waitpid option bits (kernel-identical). */ #define WNOHANG 1 /* do not block; return 0 if no child has exited */ #define WUNTRACED 2 /* also report stopped children */ #define WCONTINUED 8 /* also report continued children */ /* * waitid-only option bits (kernel-identical; XSI). WSTOPPED shares its * value with WUNTRACED, so the two names are interchangeable where both * apply. */ #define WEXITED 4 /* wait for exited children */ #define WSTOPPED 2 /* wait for stopped children */ #define WNOWAIT 0x01000000 /* report but do not reap */ /* Status decode macros. The argument is the raw wait status word. */ /* True when the child terminated normally via exit() or _exit(). */ #define WIFEXITED(s) (((s) & 0x7f) == 0) /* Exit status of a normally terminated child (WIFEXITED true). */ #define WEXITSTATUS(s) (((s) & 0xff00) >> 8) /* * True when the child was killed by a signal. The 0x7f exclusion keeps the * stop code (0x7f) from being misread as a terminating signal. */ #define WIFSIGNALED(s) (((s) & 0x7f) != 0 && ((s) & 0x7f) != 0x7f) /* Number of the signal that killed the child (WIFSIGNALED true). */ #define WTERMSIG(s) ((s) & 0x7f) /* True when the child is stopped by a signal (WUNTRACED). */ #define WIFSTOPPED(s) (((s) & 0xff) == 0x7f) /* Number of the signal that stopped the child (WIFSTOPPED true). */ #define WSTOPSIG(s) WEXITSTATUS(s) /* True when the child was resumed by SIGCONT (WCONTINUED). */ #define WIFCONTINUED(s) ((s) == 0xffff) /* True when the killed child dumped core (XSI/Linux extension, bit 0x80). */ #define WCOREDUMP(s) (((s) & 0x80) != 0) /* * si_code values reported by waitid() (kernel-identical). POSIX defines * these in , which does not exist yet; guarded per name so the * future signal.h can define them without a redefinition warning. */ #ifndef CLD_EXITED #define CLD_EXITED 1 /* child exited normally */ #define CLD_KILLED 2 /* child killed by a signal */ #define CLD_DUMPED 3 /* child killed by a signal and dumped core */ #define CLD_TRAPPED 4 /* child stopped by a trace event */ #define CLD_STOPPED 5 /* child stopped by a signal */ #define CLD_CONTINUED 6 /* child resumed by SIGCONT */ #endif /* * Minimal siginfo_t, sized and laid out to match the kernel's x86_64 * siginfo_t (128 bytes) for the fields waitid() fills: si_signo, si_errno, * si_code at offsets 0/4/8, then the wait-fields si_pid/si_uid/si_status at * offsets 16/20/24. The union is 8-aligned (si_utime/si_stime are 8-byte * clock_t in both the kernel and glibc layouts), so it starts at offset 16 * with implicit padding after si_code. The kernel copies the full 128 bytes, * so the size must stay 128; the pad member guarantees it and the static * asserts pin the layout. The signal-handling fields (si_addr, si_value, * timers, ...) are deliberately absent — the future owns the * complete siginfo_t and must reconcile this guard. */ #ifndef VLIBC_INTERNAL_SIGINFO_DEFINED #define VLIBC_INTERNAL_SIGINFO_DEFINED typedef struct { int si_signo; int si_errno; int si_code; union { struct { pid_t si_pid; /* 16 */ uid_t si_uid; /* 20 */ int si_status; /* 24 */ long si_utime; /* 32 — 8-byte clock_t, matches the kernel/glibc ABI */ long si_stime; /* 40 */ }; int vlibc_siginfo_pad[28]; /* union sized 112 so the struct stays 128 */ }; } siginfo_t; _Static_assert(sizeof(siginfo_t) == 128, "siginfo_t must match the kernel size"); _Static_assert(offsetof(siginfo_t, si_pid) == 16, "si_pid must sit at offset 16"); #endif /* Level 1 (POSIX base). */ /* * Wait for any child to terminate or stop and store its status in * *stat_loc (NULL skips the store); return the child pid, or -1 with * errno set. Equivalent to waitpid(-1, stat_loc, 0). */ pid_t wait(int *stat_loc); /* * Wait for the child identified by pid (-1: any child, 0: any child in the * calling process group, < -1: any child in the process group -pid) and * store its status in *stat_loc (NULL skips the store). options are the * WNOHANG/WUNTRACED/WCONTINUED bits. Return the child pid, 0 when WNOHANG * found nothing, or -1 with errno set. */ pid_t waitpid(pid_t pid, int *stat_loc, int options); /* * Wait for a child selected by idtype/id (P_ALL, P_PID, P_PGID) and fill * *infop with the siginfo details (si_pid, si_uid, si_status and a CLD_* * si_code); options are the WEXITED/WSTOPPED/WCONTINUED/WNOHANG/WNOWAIT * bits. Return 0, or -1 with errno set. infop must point to at least * 128 bytes (the kernel writes a full siginfo). */ int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); #if VLIBC_LEVEL_GE(2) /* Level 2 (muslmimic): XSI. */ /* * struct rusage is defined by , which does not exist yet; * a forward declaration is enough to pass a pointer through to the kernel. */ struct rusage; /* * Like waitpid(-1, stat_loc, options), and additionally store resource * usage in *rusage (NULL skips the store); return the child pid, or -1 * with errno set. XSI. */ pid_t wait3(int *stat_loc, int options, struct rusage *rusage); /* * Like waitpid(), and additionally store resource usage in *rusage (NULL * skips the store); return the child pid, or -1 with errno set. XSI. */ pid_t wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage); #endif /* VLIBC_LEVEL_GE(2) */ #ifdef __cplusplus } #endif #endif /* VLIBC_SYS_WAIT_H */