Signal handler async safe functions - c++

Is there a way I can call non async safe functions from within a signal handler? Or is this impossible?
I am not looking for setting a flag from within the signal handler and then print something in my "main code" but in this case the signal handlers will define the logical flow of my program in itself.

Technically you can call or write any function(s) inside the signal handler there is nothing preventing you from doing it.
The reason why its discouraged is that, when a signal handler is handling your operation, there could be another signal raised which could make the signal handler jump to the higher priority signal handler.
This kind of leads to race and hard to debug problems as we are not aware of the ordering of the handling of signals.
Thats the reason why the signal handlers are supposed to be light to avoid hard to debug race conditions and usually we set flags to indicate a signal has been raised and handle it in the main or another thread that reads these flags.

Is there a way I can call non async safe functions from within a signal handler? Or is this impossible?
No. Not safely. Doing so results in undefined behavior - most likely deadlocks, but other things can happen, too.
The reason any function call is labeled as "async signal safe" is for the very purpose of marking it as safe to call from within a signal handler.
From the signal(7) Linux man page:
Async-signal-safe functions
A signal handler function must be very careful, since processing
elsewhere may be interrupted at some arbitrary point in the execution
of the program. POSIX has the concept of "safe function". If a
signal interrupts the execution of an unsafe function, and handler
calls an unsafe function, then the behavior of the program is
undefined.
POSIX.1-2004 (also known as POSIX.1-2001 Technical Corrigendum 2)
requires an implementation to guarantee that the following functions
can be safely called inside a signal handler:
...
If the function call is not listed, it's not safe to call it from within a signal handler.

Related

Not safe to print in signal handler? [duplicate]

I am still a little confused as to why exactly it is unsafe to receive a signal and call a non async safe function from within that signal handler. Could someone explain the reasoning behind this and possibly try and give me some references that I can follow to read up more on this myself?
In other words I am asking why it is unsafe to say call printf from within a signal handler. Is it because of intra-process issues and possible race conditions resulting from two possible calls to printf without protection or is it because of inter process races to the same resource (in this example stdout). Say a thread within process A is calling printf and another thread receives the signal and then calls printf. Is it possibly because the kernel here will not know what to do because it will not be able to distinguish between the two calls.
Say a thread within process A is calling printf and another thread
receives the signal and then calls printf. Is it possibly because the
kernel here will not know what to do because it will not be able to
distinguish between the two calls.
It's not the kernel that will have issues. It's your application itself. printf is not a kernel function. It's a function in the C library, that your application uses. printf is actually a fairly complicated function. It supports a wide variety of output formatting.
The end result of this formatting is a formatted output string that's written to standard output. That process in and of itself also involves some work. The formatted output string gets written into the internal stdout file handle's output buffer. The output buffer gets flushed (and only at this point the kernel takes over and writes a defined chunk of data to a file) whenever certain defined conditions occur, namely when the output buffer is full, and/or whenever a newline character gets written to the output stream.
All of that is supported by the output buffer's internal data structures, which you don't have to worry about because it's the C library's job. Now, a signal can arrive at any point while printf does its work. And I mean, at any time. It might very well arrive while printf is in the middle of updating the output buffer's internal data structure, and they're in a temporarily inconsistent state because printf hasn't yet finished updating it.
Example: on modern C/C++ implementations, printf may not be signal-safe, but it is thread safe. Multiple threads can use printf to write to standard output. It's the threads' responsibility to coordinate this process amongst themselves, to make sure that the eventual output actually makes sense, and it's not jumbled up, at random, from multiple threads' output, but that's beside the point.
The point is that printf is thread safe, and that typically means that somewhere there's a mutex involved in the process. So, the sequence of events that might occur is:
printf acquires the internal mutex.
printf proceeds with its work with formatting the string and writing it to stdout's output buffer.
before printf is done, and can release the acquired mutex, a signal arrives.
Now, the internal mutex is locked. The thing about signal handlers is that it's generally not specified which thread, in a process, gets to handle the signal. A given implementation might pick a thread at random, or it might always pick the thread that's currently running. In any case, it can certainly pick the thread that has locked the printf, here, in order to handle the signal.
So now, your signal handler runs, and it also decides to call printf. Because printf's internal mutex is locked, the thread has to wait for the mutex to get unlocked.
And wait.
And wait.
Because, if you were keeping track of things: the mutex is locked by the thread that was interrupted to service the signal. The mutex won't get unlocked until the thread resumes running. But that won't happen until the signal handler terminates, and the thread resumes running, but the signal handler is now waiting for the mutex to get unlocked.
You're boned.
Now, of course, printf might use the C++ equivalent of std::recursive_mutex, to avoid this problem, but even this won't solve all possible deadlocks that could get introduced by a signal.
To summarize, the reason why it's "unsafe to receive a signal and call a non async safe function from within that signal handler" is because it's not, by definition. It's not safe to call a non-async safe function from within the signal handler" because the signal is an asynchronous event, and since it's not an async-safe function, you can't, by definition. Water is wet because it's water, and an async-unsafe function cannot be called from an asynchronous signal handler.

Why can only async-signal-safe functions be called from signal handlers safely?

I am still a little confused as to why exactly it is unsafe to receive a signal and call a non async safe function from within that signal handler. Could someone explain the reasoning behind this and possibly try and give me some references that I can follow to read up more on this myself?
In other words I am asking why it is unsafe to say call printf from within a signal handler. Is it because of intra-process issues and possible race conditions resulting from two possible calls to printf without protection or is it because of inter process races to the same resource (in this example stdout). Say a thread within process A is calling printf and another thread receives the signal and then calls printf. Is it possibly because the kernel here will not know what to do because it will not be able to distinguish between the two calls.
Say a thread within process A is calling printf and another thread
receives the signal and then calls printf. Is it possibly because the
kernel here will not know what to do because it will not be able to
distinguish between the two calls.
It's not the kernel that will have issues. It's your application itself. printf is not a kernel function. It's a function in the C library, that your application uses. printf is actually a fairly complicated function. It supports a wide variety of output formatting.
The end result of this formatting is a formatted output string that's written to standard output. That process in and of itself also involves some work. The formatted output string gets written into the internal stdout file handle's output buffer. The output buffer gets flushed (and only at this point the kernel takes over and writes a defined chunk of data to a file) whenever certain defined conditions occur, namely when the output buffer is full, and/or whenever a newline character gets written to the output stream.
All of that is supported by the output buffer's internal data structures, which you don't have to worry about because it's the C library's job. Now, a signal can arrive at any point while printf does its work. And I mean, at any time. It might very well arrive while printf is in the middle of updating the output buffer's internal data structure, and they're in a temporarily inconsistent state because printf hasn't yet finished updating it.
Example: on modern C/C++ implementations, printf may not be signal-safe, but it is thread safe. Multiple threads can use printf to write to standard output. It's the threads' responsibility to coordinate this process amongst themselves, to make sure that the eventual output actually makes sense, and it's not jumbled up, at random, from multiple threads' output, but that's beside the point.
The point is that printf is thread safe, and that typically means that somewhere there's a mutex involved in the process. So, the sequence of events that might occur is:
printf acquires the internal mutex.
printf proceeds with its work with formatting the string and writing it to stdout's output buffer.
before printf is done, and can release the acquired mutex, a signal arrives.
Now, the internal mutex is locked. The thing about signal handlers is that it's generally not specified which thread, in a process, gets to handle the signal. A given implementation might pick a thread at random, or it might always pick the thread that's currently running. In any case, it can certainly pick the thread that has locked the printf, here, in order to handle the signal.
So now, your signal handler runs, and it also decides to call printf. Because printf's internal mutex is locked, the thread has to wait for the mutex to get unlocked.
And wait.
And wait.
Because, if you were keeping track of things: the mutex is locked by the thread that was interrupted to service the signal. The mutex won't get unlocked until the thread resumes running. But that won't happen until the signal handler terminates, and the thread resumes running, but the signal handler is now waiting for the mutex to get unlocked.
You're boned.
Now, of course, printf might use the C++ equivalent of std::recursive_mutex, to avoid this problem, but even this won't solve all possible deadlocks that could get introduced by a signal.
To summarize, the reason why it's "unsafe to receive a signal and call a non async safe function from within that signal handler" is because it's not, by definition. It's not safe to call a non-async safe function from within the signal handler" because the signal is an asynchronous event, and since it's not an async-safe function, you can't, by definition. Water is wet because it's water, and an async-unsafe function cannot be called from an asynchronous signal handler.

Boost Semaphores under linux and EINTR return code

In boost (I use 1.54.0) I see implementation for posix semaphore wait:
inline void semaphore_wait(sem_t *handle)
{
int ret = sem_wait(handle);
if(ret != 0){
throw interprocess_exception(system_error_code());
}
}
Manual on posix semaphore says:
ERRORS
EINTR The call was interrupted by a signal handler; see signal(7).
Am I right that boost semaphore throw exception if I send kill to the waiting thread? If so how do you handle this situation?
In my opinion, this is probably a bug in Boost.Interprocess. Please, report it to developers, at the very least they will be able to provide a rationale if this is intentional.
Commenting on signal management suggestion in the comments above. It is true that a typical multi-threaded application should mask out signals that are not intended to be processed by threads, leaving only one thread to handle signals. However, this is not a mandatory rule.
First, auxiliary threads can be spawned by libraries which do not internally handle signals, leaving that to the application. Signal handlers can potentially be called in these threads.
Second, some signals may be intentionally left unmasked to catch events related to that particular thread. For example, one can register a handler for SIGSEGV to detect segmentation errors. This handler will be invoked in the offending thread, and the application can theoretically deal with the error. Similarly, SIGUSR1 or SIGUSR2 can be used to signal application-defined events to particular threads.
The bottom line is that even though a well designed application should extract signal handling to a separate thread, libraries should not assume that and be prepared that it doesn't. In any case, throwing in case of EINTR doesn't look like a correct behavior.
The implementation looks OK. SA_RESTART flag can be used so the call is restarted automatically. http://man7.org/linux/man-pages/man7/signal.7.html

What signal might pthread_join() cause?

I had a an error condition in C++ that I cannot easily reproduce in my call to pthread_join() some signal was generated, I do not know which one, but my signal handler was called and for some reason did not print out the normal debug information on the signal that was generated. I did get a stack trace that showed:
# 2 /lib/tls/libpthread.so.0: pthread_join(...) +0x1c [0xce439c]
I reviewed the man page for pthread_join() and did not see any mention of signals.
What might have been the signal generated and what might have been the cause? This might be some kind of race condition.
http://linux.die.net/man/7/pthreads :
Signals are used in implementation internally
http://osr600doc.sco.com/man/html.PTHREAD/pthread_join.PTHREAD.html :
The wait in pthread_join is not broken by a signal.
If a thread waiting in pthread_join receives a signal that is not masked,
it will execute the signal handler, and then return to waiting in pthread_join.
Note that this behavior differs from that of pthread_cond_wait.
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fusers_25.htm :
Threadsafe: Yes
Signal Safe: No
Basically, you might be experiencing the fact that pthread_join() accepts some other signal due to some error or external event.
We cannot guess what exactly causes the signal.
P.S. The exact environment is not specified which makes decision even harder.

Portable way to catch signals and report problem to the user

If by some miracle a segfault occurs in our program, I want to catch the SIGSEGV and let the user (possibly a GUI client) know with a single return code that a serious problem has occurred. At the same time I would like to display information on the command line to show which signal was caught.
Today our signal handler looks as follows:
void catchSignal (int reason) {
std :: cerr << "Caught a signal: " << reason << std::endl;
exit (1);
}
I can hear the screams of horror with the above, as I have read from this thread that it is evil to call a non-reentrant function from a signal handler.
Is there a portable way to handle the signal and provide information to users?
EDIT: Or at least portable within the POSIX framework?
This table lists all of the functions that POSIX guarantees to be async-signal-safe and so can be called from a signal handler.
By using the 'write' command from this table, the following relatively "ugly" solution hopefully will do the trick:
#include <csignal>
#ifdef _WINDOWS_
#define _exit _Exit
#else
#include <unistd.h>
#endif
#define PRINT_SIGNAL(X) case X: \
write (STDERR_FILENO, #X ")\n" , sizeof(#X ")\n")-1); \
break;
void catchSignal (int reason) {
char s[] = "Caught signal: (";
write (STDERR_FILENO, s, sizeof(s) - 1);
switch (reason)
{
// These are the handlers that we catch
PRINT_SIGNAL(SIGUSR1);
PRINT_SIGNAL(SIGHUP);
PRINT_SIGNAL(SIGINT);
PRINT_SIGNAL(SIGQUIT);
PRINT_SIGNAL(SIGABRT);
PRINT_SIGNAL(SIGILL);
PRINT_SIGNAL(SIGFPE);
PRINT_SIGNAL(SIGBUS);
PRINT_SIGNAL(SIGSEGV);
PRINT_SIGNAL(SIGTERM);
}
_Exit (1); // 'exit' is not async-signal-safe
}
EDIT: Building on windows.
After trying to build this one windows, it appears that 'STDERR_FILENO' is not defined. From the documentation however its value appears to be '2'.
#include <io.h>
#define STDIO_FILENO 2
EDIT: 'exit' should not be called from the signal handler either!
As pointed out by fizzer, calling _Exit in the above is a sledge hammer approach for signals such as HUP and TERM. Ideally, when these signals are caught a flag with "volatile sig_atomic_t" type can be used to notify the main program that it should exit.
The following I found useful in my searches.
Introduction To Unix Signals Programming
Extending Traditional Signals
FWIW, 2 is standard error on Windows also, but you're going to need some conditional compilation because their write() is called _write(). You'll also want
#ifdef SIGUSR1 /* or whatever */
etc around all references to signals not guaranteed to be defined by the C standard.
Also, as noted above, you don't want to handle SIGUSR1, SIGHUP, SIGINT, SIGQUIT and SIGTERM like this.
Richard, still not enough karma to comment, so a new answer I'm afraid. These are asynchronous signals; you have no idea when they are delivered, so possibly you will be in library code which needs to complete to stay consistent. Signal handlers for these signals are therefore required to return. If you call exit(), the library will do some work post-main(), including calling functions registered with atexit() and cleaning up the standard streams. This processing may fail if, say, your signal arrived in a standard library I/O function. Therefore in C90 you are not allowed to call exit(). I see now C99 relaxes the requirement by providing a new function _Exit() in stdlib.h. _Exit() may safely be called from a handler for an asynchronous signal. _Exit() will not call atexit() functions and may omit cleaning up the standard streams at the implementation's discretion.
To bk1e (commenter a few posts up)
The fact that SIGSEGV is synchronous is why you can't use functions that are not designed to be reentrant. What if the function that crashed was holding a lock, and the function called by the signal handler tries to acquire the same lock?
This is a possibility, but it's not 'the fact that SIGSEGV is synchronous' which is the problem. Calling non-reentrant functions from the handler is much worse with asynchronous signals for two reasons:
asynchronous signal handlers are
(generally) hoping to return and
resume normal program execution. A
handler for a synchronous signal is
(generally) going to terminate
anyway, so you've not lost much if
you crash.
in a perverse sense, you have absolute control over when a synchronous signal is delivered - it happens as you execute your defective code, and at no other time. You have no control at all over when an async signal is delivered. Unless the OP's own I/O code is ifself the cause of the defect - e.g. outputting a bad char* - his error message has a reasonable chance of succeeding.
Write a launcher program to run your program and report abnormal exit code to the user.