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.
Related
I need to run a cleanup before exiting service upon termination (by Linux systemctl stop my-srv
I came up so far with 2 solutions:
void signal_callback(int code)
{
_exit(0);
}
. . .
void main.. {
signal(SIGTERM, signal_callback)
fgetc(stdin); // wait for signal
}
on what thread the signal_callback is called? will it be the same thread which registered the callback? I mean if I call signal on main thread and then call exit in the signal_callback - will the application terminate gracefully?
on what thread the signal_callback is called?
Depends on how you send the signal.
If you send a signal using raise, then the callback will be called in the same thread.
If you send a signal using pthread_kill, then the signal callback will be called in the thread that whose id was passed to pthread_kill.
If you send a signal using kill then I think it's best to quote documentation:
POSIX.1 requires that if a process sends a signal to itself, and
the sending thread does not have the signal blocked, and no other
thread has it unblocked or is waiting for it in sigwait(3), at
least one unblocked signal must be delivered to the sending
thread before the kill() returns.
There will be differences if
if I ... call exit in the signal_callback - will the application terminate gracefully?
No, exit is not an async safe function. It's not OK to call it from a signal handler.
Regarding edit: _exit is async safe so you may call it. But it won't call registered cleanup functions, nor would the stack be unwound, so I wouldn't describe it as "graceful" as such.
P.S. main must return int.
By default, signals are sent to the process; not to any specific threads that process may have. If there are multiple threadss, which thread handles signal(s) isn't specified by standards.
You can of course mask the signals so that certain threads don't receive them
or that only a specific thread handles the signals. See pthread_sigmask for Linux.
if I call signal on main thread and then call exit in the signal_callback - will the application terminate gracefully?
What "gracefully" means depends on your program. If you setup a signal handler as you have, it'd simply exit upon receiving the signal. Whether that the process dies cleanly depends on what it was doing when it received signal such as whether any cleanup action is needed, resources need to be released (the ones not released automatically upon exit), etc.
I have a strange issue with C++11 threads.
Unfortunately I cannot paste the full example (given the complexity) and I cannot replicate the issue on a simpler example.
So the problem is that I have a thread which is running (nor join nor detach has been called on it).
At some point another thread wants to stop this thread. The implementation simply set a boolean variable to false, and the call the join to wait for thread termination.
Well, the problem is the join.
I checked that the current thread (calling the join) is different from the joined thread and joinable() returns true.
Nevertheless this exception occurs:
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: thread::join failed: No such process
This happens on macOS 10.11 but I had a colleague of mine test it on linux and it does not occur.
Any clue?
This might happen if you call fork() after creating additional threads in parent process. One important thing that differs the child process from the parent is that the child has only one thread.
So all C++ code which thinks there's a thread will be fooled and join() will throw
"No such process". In this case because native call will return ESRCH.
You shouldn't create threads before calling fork().
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.
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
I have a main(), which spawns a thread, and then joins to it.
I want to be able to CTRL-C the program, so I would install SIGINT handler in main (the spawn thread will ignore this signal). When I am in sig-handler I will cancel the spawned thread with cancel(), but what happens with the current 'join()', which was active during the signal invocation.
My guess is that I will get EAGAIN or EINTR, and I would have to make join() in loop. Am I right? Thank you.
The question is: Is this legal with mulithreading. I don't mind to just set a flag withing SIGINT handle, but what happens with the join() call?
Signals and threads? Here be dragons! You have to fully-specify the masks, or else any thread may receive the signal.
The signal handler should generally not assume it is running in the "main" thread. Rather, it should post a message and return, analagously to thread interruption. The main thread can pick this up later in an event loop or whatever and then join.
std::thread::join() has a void return type, so cannot return EINTR. On POSIX platforms it is likely a wrapper around pthread_join, which does not return EINTR. Joining a thread should not return or throw until the thread has been successfully joined-with, provided it is called on a joinable thread.
As an aside, it may not be safe to cancel the thread from a signal handler. std::thread does not have a cancel() member function, so I presume you have written your own. You therefore need to check that it is safe for use in a signal handler --- pthread_cancel() is not listed as a function that is safe to call from a signal handler, for example.