--- name: wait signature: 'wait' since: 5.0 status: documented categories: ["Processes"] --- ```{index} single: wait; Perl built-in ``` *[Processes](../perlfunc-by-category)* # wait Block until any child process exits and reap it. `wait` is the simplest front end to the underlying `wait(2)` system call. It suspends the current process until one of its children terminates, collects that child's exit status into [`$?`](../perlvar) and [`${^CHILD_ERROR_NATIVE}`](../perlvar), and returns the reaped child's PID. If there are no children to wait on, it returns `-1` immediately. It is exactly equivalent to [`waitpid(-1, 0)`](waitpid). ## Synopsis ```perl my $pid = wait; ``` ## What you get back The PID of the child that was reaped (a positive integer), or `-1` if there are no unreaped children left to wait on. The child's status goes into [`$?`](../perlvar); the raw, OS-specific status word goes into [`${^CHILD_ERROR_NATIVE}`](../perlvar). To decode [`$?`](../perlvar) after a successful `wait`: ```perl my $exit = $? >> 8; # normal exit code (0..255) my $signal = $? & 0x7f; # termination signal, if any my $core = $? & 0x80; # core-dump flag ``` A `-1` return does **not** always mean "never had any children" — it can also mean "something already reaped them for me" (see below). ## Global state it touches - [`$?`](../perlvar) — set to the reaped child's 16-bit wait status (high byte: exit code, low byte: termination signal and core flag). Also readable as [`$CHILD_ERROR`](../perlvar) under `use English`. - [`${^CHILD_ERROR_NATIVE}`](../perlvar) — the platform's raw status word, for callers that want to use POSIX macros (`WIFEXITED`, `WEXITSTATUS`, `WIFSIGNALED`, `WTERMSIG`) from [`POSIX`](../../POSIX). - [`%SIG`](../perlvar) — if [`$SIG{CHLD}`](../perlvar) is set to `'IGNORE'`, or a handler in it calls `wait` itself, this call's result changes. See *Edge cases*. ## Examples Fork a worker, do something, then reap it: ```perl my $pid = fork // die "fork: $!"; if ($pid == 0) { # child exec "/usr/bin/true" or die "exec: $!"; } my $reaped = wait; # blocks until the child exits die "unexpected pid" if $reaped != $pid; printf "child %d exited %d\n", $reaped, $? >> 8; ``` Reap every outstanding child in a loop. `wait` returns `-1` once the process has none left: ```perl while ((my $kid = wait) > 0) { warn "reaped $kid, status " . ($? >> 8) . "\n"; } ``` Distinguish normal exit from signal termination: ```perl my $pid = wait; if ($pid > 0) { if ($? == 0) { say "clean exit" } elsif ($? & 0x7f) { say "killed by signal " . ($? & 0x7f) } else { say "exit " . ($? >> 8) } } ``` Decode the native status word with [`POSIX`](../../POSIX) macros, which is more portable than manual bit-shifting: ```perl use POSIX ":sys_wait_h"; my $pid = wait; if ($pid > 0 && WIFEXITED(${^CHILD_ERROR_NATIVE})) { say "exit code: ", WEXITSTATUS(${^CHILD_ERROR_NATIVE}); } ``` Non-blocking reap of every pending zombie — use [`waitpid`](waitpid) with `WNOHANG`, not `wait`: ```perl use POSIX ":sys_wait_h"; 1 while waitpid(-1, WNOHANG) > 0; ``` ## Edge cases - **No children to wait on**: returns `-1` immediately. `wait` does not block in this case — it only blocks when at least one child is still alive and unreaped. - **`$SIG{CHLD} = 'IGNORE'`**: on POSIX systems this asks the kernel to auto-reap children. Under this setting, `wait` almost always returns `-1` because the children are gone before user code can call it. [`$?`](../perlvar) is not set. If you want both fire-and-forget children **and** status reporting, use a real handler, not `'IGNORE'`. - **Custom `$SIG{CHLD}` handler**: if the handler calls `wait` (or [`waitpid`](waitpid)) itself, a subsequent `wait` in the main flow will find nothing left and return `-1`. Decide up-front which code path does the reaping. - **Interaction with [`qx//`](../perlop) and [`system`](system)**: both of these internally fork, exec, and wait on their own child. A `$SIG{CHLD}` handler that blindly calls `wait` can accidentally reap that internal child out from under [`qx//`](../perlop) or [`system`](system), leaving them unable to collect the status and typically returning `-1` with [`$!`](../perlvar) set to `ECHILD`. Handlers should loop with `waitpid(-1, WNOHANG)` and only act on PIDs they recognise. - **`$?` is only written on a successful reap**. After a `-1` return, [`$?`](../perlvar) retains whatever it had before the call. Don't inspect it unless `wait` returned a positive PID. - **Interrupted by a signal**: if a signal is delivered while `wait` is blocked and the handler returns normally, Perl restarts the wait — you do not see `EINTR` at the Perl level. If the handler [`die`](die)s or [`exit`](exit)s, control leaves `wait` the usual way for that mechanism. - **Threaded builds**: `wait` waits for children of the current process, not children of a specific thread. In a multi-threaded program the reaping thread is whichever one called `wait` first. - **Return value is a PID, not a boolean**: `if (wait) { ... }` is true for both successful reaps and `-1`. Always compare to `0` or check `> 0` explicitly, as in the loop form above. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`waitpid`](waitpid) — wait for a specific child, or poll non-blockingly with `WNOHANG`; `wait` is the `waitpid(-1, 0)` form - [`fork`](fork) — create the children that `wait` reaps - [`exec`](exec) — what a forked child typically calls to become a different program - [`system`](system) — fork + exec + wait in one call; uses its own internal `wait` and sets [`$?`](../perlvar) for you - [`kill`](kill) — send a signal to a child you no longer want to wait for - [`$?`](../perlvar) — where the reaped child's status lands, encoded as exit-code high byte plus signal/core low byte