*[Processes](../perlfunc-by-category.md)* # 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.md) and [`${^CHILD_ERROR_NATIVE}`](../perlvar.md), 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.md). ## 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.md); the raw, OS-specific status word goes into [`${^CHILD_ERROR_NATIVE}`](../perlvar.md). To decode [`$?`](../perlvar.md) 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.md) — 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.md) under `use English`. - [`${^CHILD_ERROR_NATIVE}`](../perlvar.md) — the platform’s raw status word, for callers that want to use POSIX macros (`WIFEXITED`, `WEXITSTATUS`, `WIFSIGNALED`, `WTERMSIG`) from [`POSIX`](../../POSIX.md). - [`%SIG`](../perlvar.md) — if [`$SIG{CHLD}`](../perlvar.md) 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.md) 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.md) 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.md) 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.md)) 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.md) and [`system`](system.md)**: 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.md) or [`system`](system.md), leaving them unable to collect the status and typically returning `-1` with [`$!`](../perlvar.md) 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.md) 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.md)s or [`exit`](exit.md)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.md) — wait for a specific child, or poll non-blockingly with `WNOHANG`; `wait` is the `waitpid(-1, 0)` form - [`fork`](fork.md) — create the children that `wait` reaps - [`exec`](exec.md) — what a forked child typically calls to become a different program - [`system`](system.md) — fork + exec + wait in one call; uses its own internal `wait` and sets [`$?`](../perlvar.md) for you - [`kill`](kill.md) — send a signal to a child you no longer want to wait for - [`$?`](../perlvar.md) — where the reaped child’s status lands, encoded as exit-code high byte plus signal/core low byte