Join GitHub today
[Thread.sigmask] does not mask signals #7709
Original bug ID: 7709
When using [Thread.sigmask] to mask signals in some thread (that is, to make sure that signals are received in one particular thread, for example), it seems like signals can be received even by threads for which signals are blocked.
As an example, I join a test to the bug report. In that example, 3 computation-intensive threads are launched, and the signals are blocked for those. In the main thread, I unblock the signal and setup a signal handler that raises an exception. By catching the exception, I can determine which thread handled the signal. It seems like any thread can receive the signal.
By reading the runtime of OCaml, the cause of the bug seems easy to understand: The posix thread that receives the signal sets [caml_pending_signals], and then any thread can see this flag and run the OCaml handler.
I am not sure what is the best way to fix this issue:
(a) Have a per-thread [caml_pending_signals]. When the current thread is not executing, the signal handler should access thread local storage of the current thread to set [caml_pending_signals]. The same kind of idea applies for [caml_something_to_do]. The main problem I foresee is that we will have to setup a different handler when the [Thread] module is loaded or not.
(b) Before launching an OCaml handler, check that the signal is not blocked in the current thread. If it is, then we do not do anything and let another thread handle the signal. Then, we will have to change the implementation of [unix_sigpending] to take into account [caml_pending_signals]. Moreover, while signal is pending, each minor gc pass will trigger a call to [sigprocmask], and I am not sure this has actual negligible performance cost.
Moreover, I have no idea how this will interact with #1128.
Comment author: @xavierleroy
This is a known issue since 2007 or so, see #4127.
In its current state