Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Thread.sigmask] does not mask signals #7709

Closed
vicuna opened this issue Jan 14, 2018 · 3 comments
Closed

[Thread.sigmask] does not mask signals #7709

vicuna opened this issue Jan 14, 2018 · 3 comments

Comments

@vicuna
Copy link

vicuna commented Jan 14, 2018

Original bug ID: 7709
Reporter: @jhjourdan
Assigned to: @jhjourdan
Status: resolved (set by @jhjourdan on 2018-12-19T14:10:56Z)
Resolution: fixed
Priority: normal
Severity: minor
Fixed in version: 4.08.0+dev/beta1/beta2
Category: threads
Duplicate of: #4127
Monitored by: enrico @gasche

Bug description

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.

File attachments

@vicuna
Copy link
Author

vicuna commented Jan 14, 2018

Comment author: @jhjourdan

This bug is triggered in Coq: this makes the timeout tactic sometimes miss the SIGALRM signal, and hence not stopping the current tactic in time.

@vicuna
Copy link
Author

vicuna commented Jan 14, 2018

Comment author: @xavierleroy

This is a known issue since 2007 or so, see #4127.

In its current state Thread.sigmask is basically useless. One can think of per-thread sets of pending signals and the like. But the POSIX thread semantics (deliver the async signal to any thread that doesn't block it) is questionable to begin with, so it's not clear to me we should invest efforts in reproducing the POSIX semantics in OCaml.

@vicuna vicuna closed this as completed Dec 19, 2018
@vicuna
Copy link
Author

vicuna commented Dec 19, 2018

Comment author: @jhjourdan

Fixed in #2104.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant