From 8527462b95f29731d8a0bc89c2b3d74215c36ef4 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Wed, 18 Sep 2024 23:20:02 -0700 Subject: [PATCH] Fix ECHILD with WNOHANG on Windows This change along with a patch for rsync's safe_write() function that'll that'll soon be added to superconfigure, gets rsync working. There's one remaining issue (which isn't a blocker) which is how rsync logs an error about abnormal process termination since there's currently no way for us to send non-fatal signals between processes. rsync in cosmos is restored Fixes #1240 --- libc/proc/wait4-nt.c | 16 +++++---- test/posix/wait2x_test.c | 70 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 test/posix/wait2x_test.c diff --git a/libc/proc/wait4-nt.c b/libc/proc/wait4-nt.c index 0da6a31d3..110994984 100644 --- a/libc/proc/wait4-nt.c +++ b/libc/proc/wait4-nt.c @@ -88,18 +88,20 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options, __proc_lock(); CheckForZombies: int rc = __proc_check(pid, wstatus, rusage); + + // if there's no zombies left + // check if there's any living processes + if (!rc && dll_is_empty(__proc.list)) { + __proc_unlock(); + return echild(); + } + + // otherwise return zombie or zero if (rc || (options & WNOHANG)) { __proc_unlock(); return rc; } - // there's no zombies left - // check if there's any living processes - if (dll_is_empty(__proc.list)) { - __proc_unlock(); - return echild(); - } - // get appropriate wait object // register ourself as waiting struct Proc *pr = 0; diff --git a/test/posix/wait2x_test.c b/test/posix/wait2x_test.c new file mode 100644 index 000000000..06c900ec4 --- /dev/null +++ b/test/posix/wait2x_test.c @@ -0,0 +1,70 @@ +// Copyright 2024 Justine Alexandra Roberts Tunney +// +// Permission to use, copy, modify, and/or distribute this software for +// any purpose with or without fee is hereby granted, provided that the +// above copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + int ws, rc; + + // create shared memory for synchronization + atomic_int *ready = + mmap(0, 4, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + if ((rc = waitpid(-1, &ws, WNOHANG)) != -1) + return 1; + if (errno != ECHILD) + return 2; + + // create process + int pid = fork(); + if (pid == -1) + return 3; + if (!pid) { + for (;;) + if (*ready) + break; + _Exit(0); + } + + // wait on process + if ((rc = waitpid(pid, &ws, WNOHANG)) == -1) + return 4; + if (rc != 0) + return 5; + if (ws) + return 6; + + // signal subprocess + *ready = 1; + + if ((rc = waitpid(pid, &ws, 0)) == -1) + return 7; + if (rc != pid) + return 8; + if (ws) + return 9; + + // wait again + if ((rc = waitpid(pid, &ws, WNOHANG)) != -1) + return 10; + if (errno != ECHILD) + return 11; +}