Is there a way in C to know the following information about signals:
Is certain signal is blocked now?
Are we inside a signal handling function chanin (i.e, was the current code called from function which was called as signal handler for certain signal)? If so, can I know what is the current signal?
Thanks
You can know which signals are currently blocked by calling sigprocmask with second argument null and third argument non-null (the first argument is ignored under these conditions, so pass zero). It'll fill in the sigset_t you provide as the third argument.
I'm not aware of any way to know whether there is a signal handler frame on the stack. I suppose you might be able to use the _Unwind_* family of functions somehow but it would be a horrible kludge.
Firstly, you can use sigprocmask with an empty set pointer.
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
a. how can be set to:
SIG_UNBLOCK (the signal in set are removed from the current set of blocked signals. It is legal to attempt to unblock signal which is not blocked)
b. set can be set to NULL (as you don't want to change the blocked signals)
c. If oldset is not NULL, the previous value of the signal mask is stored in oldset. Ergo, you get the blocked signals in the location whose address is stored in oldset.
Secondly, for knowing if you are in a signal handling routine, when you write the signal handler definition, you can accept int signum as a parameter, as in:
void mySignalHandler(int signum);
If you want to know so that you can block some other signals at that point of time, you could just have a blocking function at the start & unblocking function at the end (using sigprocmask()). You could even set said signals to SIG_IGN status to ignore them while handling the current signal (using signal() ).
Lastly, please read the man pages!
Edit:
Since the author says he does read them, I recommend using the apropos command to find such hard-to-find functions. For example,
$ apropos "blocked signals"
gives you around 5 hits, 1 of which is sigprocmask
Cheers!
Related
I have a program in C. I wish for it to always exit cleanly with exit code of 0 when it gets a SIGTERM. What is the earliest place I can register the signal handler? I added it at the top of my main(), but I worry it might get a sigterm just before the signal registers.
Is it possible to register a signal handler even earlier?
Yes you can. Using platform specific initializers such as gcc's __attribute((constructor)). But that's hardly a robust solution.
If you wish to "to always exit cleanly with exit code of 0 when it gets a SIGTERM", then instruct the process-spawning code to start with SIGTERM blocked.
Your main can then register a signal handler and unblock SIGTERM (with sigprocmask or pthread_sigmask, at which point the signal handler will run immediately if it had been received at any point in between process creation up to the signal-unblocking call.
Essentially, it will defer the delivery of the signal up to a point where you're ready too handle it.
(Note that if you start the process with the signal ignored rather than blocked, then any instance of the signal received up to unignoring the signal will have been lost, as if they never happened. That would seem to go against your stated requirement.)
If you can switch to C++: between start of the program and main global variables are initialized. So in theory you could have code like the following that would be run before main is called.
int f() {
signal(...);
return 0;
}
int x = f();
But you don't have a guarantee in which order global objects are initialized, so x might not be initialized first, but last.
But coming back to your original request: the time between starting the program and main is so short, why do you want to prepare against someone sending a SIGTERM in that short time? Isn't that too unlikely to happen?
If it is possible you could change the parent to ignore SIGTERM and then fork and execve. signal man page says
A child created via fork(2) inherits a copy of its parent's
signal dispositions. During an execve(2), the dispositions of
handled signals are reset to the default; the dispositions of
ignored signals are left unchanged.
So you could start your process ignoring SIGTERM until it sets a handler for SIGTERM.
I am aware that i can mask a signal from being raised when handler is executing (by using sa_mask). However, i would like to know how to mask a signal when i am updating some global variables.
Also, i would like to know how to mask a signal when a particular user defined function is executing.
Is it possible to do these 2 things?
Any help will be appreciated
Thanks
You can call "signal()" any time you want; either to a) set the signal handler to some custom code, or b) clear it by setting the handler argument to NULL.
sigaction(), of course, gives you even finer-grained control. You can call sigaction whenever you wish (for example, before updating your global variables), too.
This link might help:
http://www.linuxjournal.com/article/6483
It's possible to block signals with sigblock(). Signals blocked will be queued and released when the signal is unblocked.
HOWEVER - this is super expensive. You have to do a syscall to block and a syscall to unblock. This can be quite slow if you do it often. So there are some alternative approaches:
If you're on linux, use signalfd. You can block all signals once and redirect them to a file descriptor, then handle them whenever it's safe to do so.
Otherwise (or if async signal handling is important), you can defer signals in userspace. Before entering your critical section, set a volatile flag. In your signal handler, check for this flag; if you see it, write() to a pipe the signal number and immediately return. In your signal handler, check back for a signal on this pipe, and re-raise the signal at that point.
I am writing a multithreaded program and i have this question:
Suppose that, while executing in the main thread, i want to terminate all
child-threads. I can't just send them a termination signal cause i want them
to free dynamically allocated memory first. Can i define a specific signal handler
function in each thread function that is executed, which in turn is going to call
a cleanup function that i will write to do so? If not how can i accomplish my goal??
Thanks,
Nikos
Look at the man page for pthread_cancel:
When a cancellation requested is acted on, the following steps occur for
thread (in this order):
1. Cancellation clean-up handlers are popped (in the reverse of the order in
which they were pushed) and called. (See pthread_cleanup_push(3).)
2. Thread-specific data destructors are called, in an unspecified order. (See
pthread_key_create(3).)
3. The thread is terminated. (See pthread_exit(3).)
So you can use pthread_cancel from your main, provided you have registered you cleanup handlers correctly using the above functions.
(Do read that man page completely though, it has a lot of important information.)
Edit: (from comments) If you plan on using PTHREAD_CANCEL_DEFERRED and need to insert a cancellation point somewhere in your code, then use pthread_testcancel. This function checks if a cancellation was requested. If that is the case, the cancellation is serviced (i.e. that call never returns). Otherwise it has no effect.
The most robust strategy requires cooperation from the child threads: you set a flag that the threads periodically check and, when the flag is set, free whatever resources they're using and then terminate.
Cancellation (Mat's answer) is the correct and canonical one, but if you want a different approach, you can install a no-op signal handler using sigaction without the SA_RESTART flag and use pthread_kill with whatever signal number you chose in order to interrupt (EINTR) whatever the thread might have been blocked on. Combined with this, aix's answer works.
I've got a situation where a signal handler needs to, under certain conditions, return without unmasking itself, i.e. after returning the signal should remain blocked in the thread's signal mask. Jumping out of the signal handler with longjmp will not work because I need to return to the exact point that was interrupted like a normal signal handler return. Is there any conformant way to do this, short of using the ucontext_t which was removed from the standards? I cannot change signal handlers or dispositions; all effects must be local to the thread.
The purpose of this code has to do with some atomic operations and potential for a race condition or deadlock. Basically the potentially interrupted code looks like:
atomic_write(&thread_local_flag, 1);
atomic_dec(&global_counter);
If the flag has been set and the counter decremented, all is well and the signal handler has nothing to do, but the signal could possibly arrive between the two instructions. In this case, the signal handler wants to immediately return and let the decrement proceed, but the process is being bombarded with signals (intended to be received by all threads for an arcane synchronization purpose) and there's a possibility it could loop forever (or at least for unbounded time) processing signals while other threads never receive their signals.
If I could leave the signal blocked when the signal handler returns, there would be no problem.
Hmm, the best I've found so far.. This seems to work and does not depend on any ucontext functions, just the structure which was not removed. In the signal handler:
if (thread_local_flag) {
sigaddset(&((ucontext_t *)ctx)->uc_sigmask, sig);
return;
}
Here sig and ctx are the first and third argument to the SA_SIGINFO-type signal handler, respectively.
Any thoughts on whether this is correct usage or a horrible hack (or both)?
Any ideas on this? Is there some kind of a signal queue, or does it get dropped?
While we are at this question, is it true that signal handlers should do as minimal work as possible?
I read somewhere that a signal handler should use a pipe and just write one byte to it, indicating what the program should do. Then somewhere else the program periodically checks the pipe, and dispatches based on byte in it. (I might have misunderstood it)
Thanks, Boda Cydo.
To answer the second part of your question, "is it true that signal handlers should do as minimal work as possible?" the answer is yes, because there is a very minimal set of functions that are "async signal safe" and therefore able to be called from signal handlers. Async signal safety is kind of an enhanced form of re-entrancy. If foo() is async signal safe, that means that it's safe to call foo() within a signal handler, even if foo() was already executing when the signal was raised.
You can get the full list of async signal safe functions by looking that the section 7 man page for signal (man 7 signal). Calling any function other than one of these from within a signal handler, directly or indirectly, invokes undefined behavior.
The "write a byte to a pipe" approach is a great way to deal with signals without being restricted to async signal safe functions, especially if your program is already oriented around a select loop.
To answer the first part of your question, the default is as follows: If it's the same signal as the one currently being handled, the new signal is blocked (held in a queue) and delivered when the handler returns. If some other signal arrives, the handler for the new signal is called. c.f. the glibc manual.