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 not working under pthreads #4127

Closed
vicuna opened this issue Oct 2, 2006 · 6 comments

Comments

Projects
None yet
1 participant
@vicuna
Copy link

commented Oct 2, 2006

Original bug ID: 4127
Reporter: Claudio Sacerdoti Coen
Assigned to: @jhjourdan
Status: resolved (set by @jhjourdan on 2018-12-19T14:09:49Z)
Resolution: fixed
Priority: normal
Severity: major
Version: 3.09.2
Target version: later
Fixed in version: 4.08.0+dev/beta1/beta2
Category: threads
Has duplicate: #7709
Monitored by: enrico @gasche "Claudio Sacerdoti Coen"

Bug 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.

File attachments

@vicuna

This comment has been minimized.

Copy link
Author

commented Feb 22, 2007

Comment author: @xavierleroy

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.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 17, 2011

Comment author: @xavierleroy

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.

@vicuna

This comment has been minimized.

Copy link
Author

commented Mar 10, 2017

Comment author: @mshinwell

Jeremie has been kindly volunteered to think about this.

@vicuna

This comment has been minimized.

Copy link
Author

commented Mar 10, 2017

Comment author: @diml

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 () =
init_signal_manager_thread ();
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
process_signal signo
done
;;

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();
return Val_unit;
}

static void handle_signal(int signum)
{
if (!pthread_equal(pthread_self(), signal_manager_thread))
pthread_kill(signal_manager_thread, signum);
}


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.

@vicuna

This comment has been minimized.

Copy link
Author

commented Mar 10, 2017

Comment author: @mshinwell

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.

@vicuna

This comment has been minimized.

Copy link
Author

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
You can’t perform that action at this time.