Skip to content

Commit 5259673

Browse files
committed
Fix signal masking race in worker_loop
If an OCaml signal handler runs in a Lwt worker thread then the process will dereference a NULL pointer and crash. The worker tried to avoid this by masking out all signals after starting, but by then it may be too late. Now, we mask out signals before creating a worker thread and then restore the mask in the main thread afterwards.
1 parent d436705 commit 5259673

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

src/unix/lwt_unix_stubs.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,25 @@ value lwt_unix_system_byte_order() {
169169
int lwt_unix_launch_thread(void *(*start)(void *), void *data) {
170170
pthread_t thread;
171171
pthread_attr_t attr;
172+
sigset_t mask, old_mask;
172173

173174
pthread_attr_init(&attr);
174175

175176
/* The thread is created in detached state so we do not have to join
176177
it when it terminates: */
177178
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
178179

180+
/* Block all signals, otherwise ocaml handlers defined with the
181+
module Sys may be executed in the new thread, oops... */
182+
sigfillset(&mask);
183+
pthread_sigmask(SIG_SETMASK, &mask, &old_mask);
184+
179185
int zero_if_created_otherwise_errno =
180186
pthread_create(&thread, &attr, start, data);
181187

188+
/* Restore the signal mask for the calling thread. */
189+
pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
190+
182191
pthread_attr_destroy(&attr);
183192

184193
return zero_if_created_otherwise_errno;
@@ -978,18 +987,11 @@ void initialize_threading() {
978987
| Worker loop |
979988
+-----------------------------------------------------------------+ */
980989

981-
/* Function executed by threads of the pool. */
990+
/* Function executed by threads of the pool.
991+
* Note: all signals are masked for this thread. */
982992
static void *worker_loop(void *data) {
983993
lwt_unix_job job = (lwt_unix_job)data;
984994

985-
#if defined(HAVE_PTHREAD)
986-
/* Block all signals, otherwise ocaml handlers defined with the
987-
module Sys may be executed in this thread, oops... */
988-
sigset_t mask;
989-
sigfillset(&mask);
990-
pthread_sigmask(SIG_SETMASK, &mask, NULL);
991-
#endif
992-
993995
/* Execute the initial job if any. */
994996
if (job != NULL) execute_job(job);
995997

0 commit comments

Comments
 (0)