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

Reply via email to