It is said that you should only call asynchronous-safe functions inside a signal handler. My question is, what constitutes asynchronous-safeness? A function which is both reentrant and thread safe is asynchronous-safe I guess? Or No?
Re-entrance and thread safety has a little or nothing to do with this. Side effects, state and interruption of those functions are facts that matter.
asynchronous-safe function [GNU Pth]
A function is asynchronous-safe,
or asynchronous-signal safe, if it can be called safely and without
side effects from within a signal handler context. That is, it must be
able to be interrupted at any point to run linearly out of sequence
without causing an inconsistent state. It must also function properly
when global data might itself be in an inconsistent state. Some
asynchronous-safe operations are listed here:
call the signal() function to reinstall a signal handler
unconditionally modify a volatile sig_atomic_t variable (as
modification to this type is atomic)
call the _Exit() function to
immediately terminate program execution
invoke an asynchronous-safe
function, as specified by your implementation
Few functions are
portably asynchronous-safe. If a function performs any other
operations, it is probably not portably asynchronous-safe.
A rule of thumb is this - only signal some condition variable from signal handler (such as futex/pthread condition, wake up epoll loop etc.).
UPDATE:
As EmployedRussian suggested, even calling pthread_cond_signal is a bad idea. I've checked the source code of the recent eglibc and it has lock/unlock pair in there. Thus, introducing a possibility for a deadlock. This leaves us with few options to signal other threads:
Using eventfd.
Changing global atomic variable and hope that SA_RESTART is not set and other threads will check our atomic.
For your own code, yes, re-entrant and thread-safe are the characteristics you need, as, depending on how you set up your signal handling mechanism, your signal handler may itself be interrupted by another signal. In general, try to do as little work as possible inside the signal handler. Setting flags to trigger special code in your normal program flow is probably all you should be doing.
For functions in the OS that you might call, check out man 7 signal for a list of what is safe to call. Note that malloc() and free() are not on the list. The pthread synchronization APIs are not on the list either, but I would think that some would have to be safe to call, so you can set a global flag safely in a signal handler.
Related
How can i run asynchrounous-unsafe code in a signal handler. I cant use a flag in my case. Could i use longjmp to jump to a different context?
In a signal handler you can only use a set of safe functions which in many cases is sufficient for complicated functionality started within a handler. You can check man pages for your system for 'signal-safety' or similar. Here is a pointer on the web: https://man7.org/linux/man-pages/man7/signal-safety.7.html
pthread synchronization functions are not on the list.
However, One of the function listed there is sem_post: https://man7.org/linux/man-pages/man3/sem_post.3.html
sem_post() is async-signal-safe: it may be safely called within a
signal handler.
So, you can implement mutex-like synchronization using semaphores within the signal handler.
I have read that TerminateThread() in WinAPI is dangerous to use.
Is pthread_kill() in Linux also dangerous to use?
Edit: Sorry I meant pthread_kill() and not pthread_exit().
To quote Sir Humphrey Appleby, the answer is "yes, and no".
In and of itself calling pthread_exit() is not dangerous and is called implicitly when your thread exits its method. However, there are a few "gotchas" if you call it manually.
All cleanup handlers are called when this is called. So if you call this method, then access some memory that the cleanup handlers have cleaned up, you get a memory error.
Similarly, after this is called, any local and thread-local variables for the thread become invalid. So if a reference is made to them you can get a memory error.
If this has already been called for the thread (implicitly or explicitly) calling it again has an undefined behaviour, and
If this is the last thread in your process, this will cause the process to exit.
If you are careful of the above (i.e. if you are careful to not reference anything about the thread after you have called pthread_exit) then it is safe to call call manually. However, if you are using C++ instead of C I would highly recommend using the std::thread class rather than doing it manually. It is easier to read, involves less code, and ensures that you are not breaking any of the above.
For more information type "man pthread_exit" which will essentially tell you the above.
Since the question has now been changed, I will write a new answer. My answer still remains "yes and no" but the reasons have changed.
pthread_kill is somewhat dangerous in that it shares the potential timing risks that is inherent in all signal handling systems. In addition there are complexities in dealing with it, specifically you have to setup a signal handler within the thread. However one could argue that it is less dangerous than the Windows function you mention. Here is why:
The Windows function essentially stops the thread, possibly bypassing the proper cleanup. It is intended as a last resort option. pthread_kill, on the other hand, does not terminate the thread at all. It simply sends a signal to the thread that the thread can respond to.
In order for this to do something you need to have registered in the thread what signals you want it to handle. If your goal is to use pthread_kill to terminate the thread, you can use this by having your signal handler set a flag that the thread can access, and having the thread check the flag and exit when it gets set. You may be able to call pthread_exit from the signal handler (I've never tried that) but it strikes me as being a bad idea since the signal comes asynchronously, and your thread is not guaranteed to still be running. The flag option I mention solves this provided that the flag is not local to the thread, allowing the signal handler to set it even if the target thread has already exited. Of course if you are doing this, you don't really need pthread_kill at all, as you can simply have your main thread set the flag at the appropriate time.
There is another option for stopping another thread - the pthread_cancel method. This method will place a cancel request on the target thread and, if the thread has been configured to be cancellable (you generally do this in the pthread_create, but you can also do it after the fact), then the next time the thread reaches a potential cancellation point (specified by pthread_testcancel but also automatically handled by many system routines such as the IO calls), it will exit. This is also safer than what Windows does as it is not violently stopping the thread - it only stops at well defined points. But it is more work than the Windows version as you have to configure the thread properly.
The Wikipedia page for "posix threads" describes some of this (but not much), but it has a pretty good "See also" and "References" section that will give you more details.
We recently had a discussion at work about signal handlers in C (Unix enviornment).
Someone mentioned that
(f)printf() is certainly thread-safe but not signal-handler safe.
What does the above statement mean? What aspect of (f)printf() make it not signal-handler safe? Is it because it accesses the stdout and stdin which are global and hence the function is not re-entrant?
Or is there some other aspect which I am missing?
There is actually fairly little that is legal to do in a signal handler directly. Instead, one must usually set some flag or trigger to do the real work outside the signal handling context. While handling a signal, the only functions you can call are those which are "async signal safe," which is described in detail here: What constitutes asynchronous-safeness
As mentioned in here: http://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy
If a function uses and modifies an object that you supply, then it is
potentially non-reentrant; two calls can interfere if they use the
same object.
In your case that object is stdout. When a signal arrives in the middle of a (f)printf() and if you use (f)printf in handler, both data could be corrupted as they operate on the same stream, stdout. Reentrancy is the root cause in that case. Even if you use the stream in just signal handler, two signal handlers can interfere.
I want to set up a signal handler for SIGSEGV, SIGILL and possibly a few other signals that, rather than terminating the whole process, just terminates the offending thread and perhaps sets a flag somewhere so that a monitoring thread can complain and start another thread. I'm not sure there is a safe way to do this. Pthreads seems to provide functions for exiting the current thread, as well as canceling another thread, but these potentially call a bunch of at-exit handlers. Even if they don't, it seems as though there are many situations in which they are not async-signal-safe, although it is possible that those situations are avoidable. Is there a lower-level function I can call that just destroys the thread? Assuming I modify my own data structures in an async-signal-safe way, and acquire no mutexes, are there pthread/other global data structures that could be left in an inconsistent state simply by a thread terminating at a SIGSEGV? malloc comes to mind, but malloc itself shouldn't SIGSEGV/SIGILL unless the libc is buggy. I realize that POSIX is very conservative here, and makes no guarantees. As long as there's a way to do this in practice I'm happy. Forking is not an option, btw.
If the SIGSEGV/SIGILL/etc. happens in your own code, the signal handler will not run in an async-signal context (it's fundamentally a synchronous signal, but would still be an AS context if it happened inside a standard library function), so you can legally call pthread_exit from the signal handler. However, there are still issues that make this practice dubious:
SIGSEGV/SIGILL/etc. never occur in a program whose behavior is defined unless you generate them via raise, kill, pthread_kill, sigqueue, etc. (and in some of these special cases, they would be asynchronous signals). Otherwise, they're indicative of a program having undefined behavior. If the program has invoked undefined behavior, all bets are off. UB is not isolated to a particular thread or a particular sequence in time. If the program has UB, its entire output/behavior is meaningless.
If the program's state is corrupted (e.g. due to access-after-free, use of invalid pointers, buffer overflows, ...) it's very possible that the first faulting access will happen inside part of the standard library (e.g. inside malloc) rather than in your code. In this case, the signal handler runs in an AS-safe context and cannot call pthread_exit. Of course the program already has UB anyway (see the above point), but even if you wanted to pretend that's not an issue, you'd still be in trouble.
If your program is experiencing these kinds of crashes, you need to find the cause and fix it, not try to patch around it with signal handlers. Valgrind is your friend. If that's not possible, your best bet is to isolate the crashing code into separate processes where you can reason about what happens if they crash asynchronously, rather than having the crashing code in the same process (where any further reasoning about the code's behavior is invalid once you know it crashes).
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.