|Anonymous | Login | Signup for a new account||2019-01-17 17:42 CET|
|Main | My View | View Issues | Change Log | Roadmap|
|View Issue Details|
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0004127||OCaml||threads||public||2006-10-02 16:01||2018-12-19 15:09|
|Reporter||Claudio Sacerdoti Coen|
|Target Version||later||Fixed in Version||4.08.0+dev|
|Summary||0004127: Thread.sigmask not working under pthreads|
|Description||Thread.sigmask seems to be ignored.|
I attach an ocaml program and the "equivalent" C code.
The two programs set a signal handler for SIGINT and then create two more
threads. Each thread uses sigmask to block SIGINT. SIGINT should now be received
only from the parent thread. In Ocaml any thread can still receive the SIGINT,
as if Thread.sigmask behaves as the identity function.
|Tags||No tags attached.|
|Attached Files|| thread_mask.c [^] (636 bytes) 2006-10-02 16:01 [Show Content]
a.ml [^] (867 bytes) 2006-10-02 16:02 [Show Content]
I confirm the problem. It comes from the fact that the set of pending signals is global rather than per-thread. There is no easy fix, but I keep that in my to do list.
I've been sleeping on this PR for way too long, so I'm un-assigning it from me.
Here is my analysis. The kernel delivers the signal to one of the threads that doesn't block it. However, if this thread is outside a blocking section, it cannot act on it immediately and instead records the signal as pending in a *global* data structure. Other threads poll this data structure periodically and can decide to handle the signal even if they block it themselves (or, more exactly, blocked it at the time the signal was received). In effect, Thread.sigmask is useless.
|Jeremie has been kindly volunteered to think about this.|
From my experience, the most reliable way to deal with signals in a multi-threaded program is to handle them from a single thread with [Thread.wait_signal] and redirect signals to this particular thread if they are received from another thread, using a pure C signal handler.
This is from a project where I did this:
-----[ ml code ]-----
external init_signal_manager_thread : unit -> unit = "lt_term_init_signal_manager_thread"
let signal_manager_loop () =
ignore (Thread.sigmask SIG_BLOCK sigs_i_am_interested_in : int list);
while true do
let signo = Thread.wait_signal sigs_i_am_interested_in in
let init () = ignore (Thread.create signal_manager_loop () : Thread.t)
-----[ C code ]-----
static pthread_t signal_manager_thread = 0;
CAMLprim value lt_term_init_signal_manager_thread()
signal_manager_thread = pthread_self();
static void handle_signal(int signum)
if (!pthread_equal(pthread_self(), signal_manager_thread))
Then [process_signal] is free to handle or deliver the signal to another thread via some other mechanism. I think that this is even better than handling signals directly in a single-thread application, since you know exactly the context in which the code processing the signal will be executed.
Fixing this ticket seems like it would be complicated, and even if it's fixed it doesn't help programmers as they have to be extremely careful about what they do from a signal handler. I'm wondering if it wouldn't be worth simply providing an API to handle signal in the way I describe and document that this is the recommended way to handle signals in multi-threaded applications.
|I also wondered whether this should be thought about in the context as to how the multicore branch is going to handle things like this.|
|Fixed in GPR#2104|
|2006-10-02 16:01||Claudio Sacerdoti Coen||New Issue|
|2006-10-02 16:01||Claudio Sacerdoti Coen||File Added: thread_mask.c|
|2006-10-02 16:02||Claudio Sacerdoti Coen||File Added: a.ml|
|2006-11-15 16:13||doligez||Status||new => acknowledged|
|2007-02-22 11:12||xleroy||Note Added: 0003932|
|2007-02-22 11:12||xleroy||Assigned To||=> xleroy|
|2007-02-22 11:12||xleroy||Status||acknowledged => confirmed|
|2011-12-17 09:49||xleroy||Note Added: 0006351|
|2011-12-17 09:49||xleroy||Assigned To||xleroy =>|
|2012-07-06 16:41||doligez||Target Version||=> 4.01.0+dev|
|2012-07-31 13:37||doligez||Target Version||4.01.0+dev => 4.00.1+dev|
|2012-09-06 19:23||frisch||Target Version||4.00.1+dev => later|
|2016-12-07 17:01||shinwell||Category||OCaml general => OCaml otherlibs|
|2017-02-23 16:42||doligez||Category||OCaml otherlibs => otherlibs|
|2017-03-10 17:53||shinwell||Note Added: 0017622|
|2017-03-10 17:53||shinwell||Assigned To||=> dim|
|2017-03-10 17:53||shinwell||Status||confirmed => assigned|
|2017-03-10 18:19||dim||Note Added: 0017624|
|2017-03-10 18:27||shinwell||Note Added: 0017625|
|2018-01-14 11:01||xleroy||Relationship added||has duplicate 0007709|
|2018-01-14 12:36||xleroy||Category||otherlibs => threads|
|2018-12-19 14:52||jacques-henri.jourdan||Note Added: 0019509|
|2018-12-19 14:52||jacques-henri.jourdan||Assigned To||dim => jacques-henri.jourdan|
|2018-12-19 15:09||jacques-henri.jourdan||Status||assigned => resolved|
|2018-12-19 15:09||jacques-henri.jourdan||Fixed in Version||=> 4.08.0+dev|
|2018-12-19 15:09||jacques-henri.jourdan||Resolution||open => fixed|
|Copyright © 2000 - 2011 MantisBT Group|