help debugging flaky posix/tst-waitid.c test

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Feb 12 12:33:15 GMT 2025



On 08/02/25 12:46, Aurelien Jarno wrote:
> Hi,
> 
> The posix/tst-waitid.c appears to be flaky, although with a low
> probability to fail, but that's bad for continuous integration. Under
> heavy load, it crashes around once over 80000 times in my tests, but
> there is a way to increase the probability (see below). This happens at
> least on aarch64, riscv64 and x86-64, so it does not seems architecture
> specific at a first glance.
> 
> When it happens, it fails with:
> 
>   tst-waitid.c:73: numeric comparison failure
>      left: 0 (0x0); from: siginfo.si_status
>     right: 19 (0x13); from: status
>   error: 1 test failures
> 
> This happens for the test on lines 156-173, which basically:
> - send a SIGSTOP to the child
> - wait for the child to appear in "T" state in /proc/$pid/status
> - call waitid with WEXITED|WSTOPPED on the child
> - call sigwaitinfo on the child
> 
> In that later call, the siginfo.si_status field on the child ends-up
> with 0 instead of SIGSTOP.
> 
> I have done some more tests on a separate code and it seems that this
> happens when kill, waitid and sigwaitinfo are called very quickly after
> each other. My guess is that this behaviour is explained by the
> following comment in that code:
> 
>   /* Wait the child stop.  The waitid call below will block until it has
>      stopped, but if we are real quick and enter the waitid system call
>      before the SIGCHLD has been generated, then it will be discarded and
>      never delivered.  */
> 
> It seems that the call to support_process_state_wait (pid, stop_state)
> should prevent that, but I wonder if there is a small race condition
> left.  What I observed is that the 10ms nanosleep in
> support_process_state_wait between check of /proc/$pid/status makes the
> issue less probable. In other word, the following patch increases the
> chances for the tst-waitid test to fail:
> 
> --- a/support/support_process_state.c
> +++ b/support/support_process_state.c
> @@ -80,9 +80,6 @@ support_process_state_wait (pid_t pid, enum support_process_state state)
>  
>        rewind (fstatus);
>        fflush (fstatus);
> -
> -      if (nanosleep (&(struct timespec) { 0, 10000000 }, NULL) != 0)
> -	FAIL_EXIT1 ("nanosleep: %m");
>      }
>  
>    free (line);
> 
> Of course using strace here just hides the issue. Any idea how to debug
> or fix the issue?

It seems that we can't really rely on siginfo_t::si_status being SIGSTOP
after a waitid call that returns info.si_status equal to SIGSTOP. Skimming
through kernel code, it seems that for CLD_STOPPED the si_status is obtained
from tsk->signal->group_exit_code (kernel/signal.c - do_notify_parent_cldstop),
but I can't really tell why on how it can be zero in this scenario.

The tools/testing/selftests/pidfd/pidfd_wait.c also checks CLD_STOPPED,
but it does not check si_status.  I think we should ignore it for now.


More information about the Libc-alpha mailing list