diff options
author | Rich Felker <dalias@aerifal.cx> | 2023-02-11 19:13:10 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2023-02-12 15:05:39 -0500 |
commit | 0ab97350f01b42de0f9fd811ee08653169661859 (patch) | |
tree | 30c9b583f4e9ce595dcf0070b20b1981a18fa474 | |
parent | 711673ee772e20a74aaf301c2d7745c20c4f4d47 (diff) | |
download | musl-0ab97350f01b42de0f9fd811ee08653169661859.tar.gz musl-0ab97350f01b42de0f9fd811ee08653169661859.tar.xz musl-0ab97350f01b42de0f9fd811ee08653169661859.zip |
mq_notify: block all (application) signals in the worker thread
until the mq notification event arrives, it is mandatory that signals be blocked. otherwise, a signal can be received, and its handler executed, in a thread which does not yet exist on the abstract machine. after the point of the event arriving, having signals blocked is not a conformance requirement but a QoI requirement. while the application can unblock any signals it wants unblocked in the event handler thread, if they did not start out blocked, it could not block them without a race window where they are momentarily unblocked, and this would preclude controlled delivery or other forms of acceptance (sigwait, etc.) anywhere in the application.
-rw-r--r-- | src/mq/mq_notify.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index 8109dfb2..0e1e6c7a 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -50,6 +50,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_t td; int s; int cs; + sigset_t allmask, origmask; if (!sev || sev->sigev_notify != SIGEV_THREAD) return syscall(SYS_mq_notify, mqd, sev); @@ -64,11 +65,15 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); sem_init(&args.sem, 0, 0); + sigfillset(&allmask); + pthread_sigmask(SIG_BLOCK, &allmask, &origmask); if (pthread_create(&td, &attr, start, &args)) { __syscall(SYS_close, s); + pthread_sigmask(SIG_SETMASK, &origmask, 0); errno = EAGAIN; return -1; } + pthread_sigmask(SIG_SETMASK, &origmask, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); sem_wait(&args.sem); |