|
|
Message-ID: <20261105144541.5409-1-mailto.luca.kellermann@gmail.com>
Date: Thu, 5 Nov 2026 15:39:51 +0100
From: Luca Kellermann <mailto.luca.kellermann@...il.com>
To: musl@...ts.openwall.com
Subject: [PATCH] thrd_create: inherit signal mask from creating thread
POSIX.1-2024 requires that the new thread created by thrd_create()
inherits the signal mask from the creating thread, just like the new
thread created by pthread_create().
it seems like this was initially the case when thrd_create() was
implemented in commit 23614b0fcb4cd4d7b2e4148d3b1887b642169765. commit
04335d9260c076cf4d9264bd93dd3b06c237a639 then changed pthread_create()
to always block signals before starting new threads but restoring the
signal mask was only done for new threads started by pthread_create()
(start()), not for new threads started by thrd_create() (start_c11()).
this was before POSIX included threads.h, so it didn't violate any
specification back then (the C standard doesn't know signal masks).
---
The following program demonstrates the issue:
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <threads.h>
static int tf(void *a)
{
sigset_t s;
int i;
return sigemptyset(&s) || pthread_sigmask(0, 0, &s)
|| (i = sigismember(&s, SIGUSR1)) && i != 1
|| printf("%s does%s inherit\n", (char *)a, i ? "n't" : "") < 0;
}
static void *pf(void *a)
{
return tf(a) ? a : 0;
}
int main(void)
{
sigset_t s;
thrd_t t;
int tr;
pthread_t p;
void *pr;
return sigemptyset(&s) || sigaddset(&s, SIGUSR1)
|| pthread_sigmask(SIG_UNBLOCK, &s, 0)
|| thrd_create(&t, tf, "thrd_create") != thrd_success
|| thrd_join(t, &tr) != thrd_success || tr
|| pthread_create(&p, 0, pf, "pthread_create")
|| pthread_join(p, &pr) || pr || fflush(stdout);
}
$ ./thrd_create-sigmask
thrd_create doesn't inherit
pthread_create does inherit
Should be:
$ ./thrd_create-sigmask
thrd_create does inherit
pthread_create does inherit
I used __restore_sigs() instead of a direct syscall like in start().
It does the same but seems simpler. Can be changed if consistency is
preferred.
src/thread/pthread_create.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 087f6206d5d64165bc54ae741e77099994ae96e0..e2e6838287fe5bb76e3d8c6bd7e4d065f67e9702 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -194,24 +194,25 @@
static int start(void *p)
{
struct start_args *args = p;
int state = args->control;
if (state) {
if (a_cas(&args->control, 1, 2)==1)
__wait(&args->control, 0, 2, 1);
if (args->control) {
__syscall(SYS_set_tid_address, &args->control);
for (;;) __syscall(SYS_exit, 0);
}
}
__syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8);
__pthread_exit(args->start_func(args->start_arg));
return 0;
}
static int start_c11(void *p)
{
struct start_args *args = p;
int (*start)(void*) = (int(*)(void*)) args->start_func;
+ __restore_sigs(&args->sig_mask);
__pthread_exit((void *)(uintptr_t)start(args->start_arg));
return 0;
}
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.