Skip to content

std (posix): support for wait() (any process termination) #23982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

QSmally
Copy link

@QSmally QSmally commented May 24, 2025

With the implementation of std.posix.waitpid(pid:, flags:), the use of -1 will crash as unreachable (due to errno of CHILD) if there's no terminated children instead of allowing it to be defined behaviour and return a pid of 0.

The documentation of the waitpid syscall states:

       The waitpid() system call suspends execution of the calling thread
       until a child specified by pid argument has changed state.  By
       default, waitpid() waits only for terminated children, but this
       behavior is modifiable via the options argument, as described
       below.

For example, the nginx worker process SIGCHLD handler uses something like (source):

for ( ;; ) {
    pid = waitpid(-1, &status, WNOHANG);

    if (pid == 0) {
        return;
    }

    // ... rest omitted
}

The reasoning for using wait(flags:) as name is due to the documented behaviour of:

       The wait() system call suspends execution of the calling thread
       until one of its children terminates.  The call wait(&wstatus) is
       equivalent to:

           waitpid(-1, &wstatus, 0);

This change allow daemons/monitor processes to respawn their forks when they exit by querying all currently-terminated processes, and ignore/continue when there aren't any.

I'm currently using this PR's change for a company project, functioning correctly indicated by these logs (tested on both Linux and macOS, still need verification for other POSIX-compliant operating systems):

~/redacted-company/MultiMedia$ zig-out/bin/managedmultimedia foo bar --ifsf awd
start worker processes
MultiMedia: start worker process 29200
Event-Proxy: start worker process 29201
signal 20 received
Event-Proxy (29201): exited with status 0
MultiMedia (29200): exited with status 0

The usage within a SIGCHLD handler, for example:

while (std.posix.wait(flags)) |result|
    on_exit(result.pid, result.status);

QSmally added 2 commits May 24, 2025 20:23
~/Fork/zig$ ./build/stage3/bin/zig test lib/std/std.zig --zig-lib-dir lib
...
2810 passed; 40 skipped; 0 failed.
Copy link
Contributor

@rootbeer rootbeer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR fixes #7143.

I like this PRs approach of a dedicated wait-for-any wrapper (vs. exposing the overloaded semantics through a single wrapper).

I'm a drive-by reviewer, not a Zig team member, so feel free to ignore me and wait for a real review.

QSmally added 2 commits May 25, 2025 11:40
Darwin returns SUCCESS and exit code 0, so wait() didn't return null
@alexrp alexrp self-assigned this May 26, 2025
Copy link
Contributor

@rootbeer rootbeer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test case for waitpid looks good. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants