Hi -
> Thanks, this looks like a plausible solution. Just a few
> nitpicks/questions below. It is mainly about the comments, the basic
> idea looks good.
Thanks for the review.
> > if (gencore)
> > - printf ("%ld\n", (long) getpid ());
>
> It looks only debug output, but why remove it?
v2 moves it back.
> [...]
> I am surprised this is only necessary for the gencore case and not the
> signal case? Does the signal case synchronize a different way?
I'm not sure. v2 brings the synchronization to the other cases too.
>From 7f3aea2e57b882d587f24a0bd62b424f7bdba073 Mon Sep 17 00:00:00 2001
From: "Frank Ch. Eigler" <[email protected]>
Date: Tue, 30 Jun 2026 19:35:56 -0400
Subject: [PATCH] testsuite backtrace-child.c: Fix thread/spawn/coredump race
condition.
From: Frank Ch. Eigler <[email protected]>
Force child process to wait for main thread to advance past
pthread_create in order to avoid triggering signals/coredumps
prematurely.
Signed-off-by: Frank Ch. Eigler <[email protected]>
---
tests/backtrace-child.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/tests/backtrace-child.c b/tests/backtrace-child.c
index 8bfed478ced9..226d32396fc6 100644
--- a/tests/backtrace-child.c
+++ b/tests/backtrace-child.c
@@ -100,6 +100,7 @@ main (int argc __attribute__ ((unused)), char **argv)
#else /* __linux__ */
#include <sys/ptrace.h>
#include <signal.h>
+#include <semaphore.h>
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
@@ -113,6 +114,13 @@ main (int argc __attribute__ ((unused)), char **argv)
static int ptraceme, gencore;
+/* Synchronize between project-mayhem thread and main, blocking the
+ former until the latter has finished and returned from
+ pthread_create. Especially on slow hosts (armhf) and in --gencore
+ mode, without this synchronization, incomplete stacktraces were
+ sometimes generated from deep within pthread_create innards. */
+static sem_t gencore_go;
+
/* Execution will arrive here from jmp by an artificial ptrace-spawn signal.
*/
static NOINLINE_NOCLONE void
@@ -202,6 +210,9 @@ dummy4 (void)
static void *
start (void *arg UNUSED)
{
+ int err = sem_wait (&gencore_go); // till main() finishes pthread_create
+ assert (err == 0);
+
backtracegen ();
/* Not reached. */
abort ();
@@ -227,10 +238,16 @@ main (int argc UNUSED, char **argv)
dummy4 ();
if (gencore)
printf ("%ld\n", (long) getpid ());
+
+ int err = sem_init (&gencore_go, 0, 0);
+ assert (err == 0);
pthread_t thread;
int i = pthread_create (&thread, NULL, start, NULL);
- // pthread_* functions do not set errno.
assert (i == 0);
+ err = sem_post (&gencore_go); // we're ready for the child thread's mayhem
+ assert (err == 0);
+ // pthread_* functions do not set errno.
+
if (ptraceme)
{
errno = 0;
@@ -241,6 +258,7 @@ main (int argc UNUSED, char **argv)
pthread_join (thread, NULL);
else
raise (SIGUSR2);
+ sem_destroy (&gencore_go);
return 0;
}
--
2.55.0