I understand that about the only thing, a signal handler in ISO/C++11 is allowed to do is to read from or write to a lock free atomic variable or a volatile sig_atomic_t
(I believe, POSIX is a little bit more permissive and allows to call a bunch of system functions).
I was wondering, if there is any way, to wake up a thread that is waiting on a condition variable. I.e. something like:
#include <mutex>
#include <atomic>
#include <condition_variable>
std::mutex mux;
std::condition_variable cv;
std::atomic_bool doWait{ true };
void signalHandler(int){
doWait = false;
cv.notify_one();
}
int main() {
//register signal handler
//Do some stuff
{//wait until signal arrived
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, []{return !doWait; });
}
//Do some more stuff
}
Which has at least two problems:
notify_one()
in a signal handler (corrct me if I'm wrong)doWait
and when the thread goes to sleep, so it would never wake up (obviously, I can't lock the mutex in the signalHander to avoid that). So far, the only solution I can see is to implement busy waiting on the doWait
variable (probably sleep for a couple of milliseconds in each iteration), which strikes me as quite inefficient.
Note that even though, my program above has only one thread, I labeled my question with multithreading, because it is about thread control primitives. If there is no solution in standard c++ I'd be willing to accept a solution using Linux/POSIX specific functions.
It is not safe to use the pthread_cond_signal() function in a signal handler that is invoked asynchronously.
The pthread_cond_signal() call unblocks at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond). The pthread_cond_broadcast() call unblocks all threads currently blocked on the specified condition variable cond.
signal is a per process call, not a per thread one, if you call it it sets the handler for all threads in the process. Signals and threads is a complex topic.
The signal is delivered once to any thread that is configured to receive it. The thread, which is asynchronously handling the signal, stops whatever it is doing and jumps to the configured signal handler. The flow of the execution in the remaining threads is unaffected.
Assuming that your vendor's standard library uses the pthread_cond_*
functions to implement C++11 condition variables (libstdc++ and libc++ do this), the pthread_cond_*
functions are not async-signal-safe so cannot be invoked from a signal handler.
From http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_broadcast.html:
It is not safe to use the pthread_cond_signal() function in a signal handler that is invoked asynchronously. Even if it were safe, there would still be a race between the test of the Boolean pthread_cond_wait() that could not be efficiently eliminated.
Mutexes and condition variables are thus not suitable for releasing a waiting thread by signaling from code running in a signal handler.
If you're comfortable using semaphores, sem_post
is designated async-signal-safe. Otherwise, your options for signal handling are the usual ones: the classic self-pipe, a signal handling thread blocked on sigwait
/sigwaitinfo
, or platform-specific facilities (Linux signalfd
, etc.).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With