从信号处理程序中唤醒线程
Waking up thread from signal handler
我知道 ISO/C++11 中的信号处理程序唯一允许做的事情是读取或写入无锁原子变量或 volatile sig_atomic_t
(我相信,POSIX 稍微宽松一点,允许调用一堆系统函数)。
我想知道是否有任何方法可以唤醒正在等待条件变量的线程。 IE。类似于:
#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
}
其中至少有两个问题:
- 我相信,我不允许在信号处理程序中调用
notify_one()
(如果我错了请纠正我)
- 信号可能恰好在检查
doWait
和线程进入休眠之间到达,因此它永远不会醒来(显然,我无法在 signalHander 中锁定互斥锁来避免这种情况) .
到目前为止,我能看到的唯一解决方案是在 doWait
变量上实现忙等待(可能在每次迭代中休眠几毫秒),这让我觉得效率很低。
请注意,尽管我上面的程序只有一个线程,但我用多线程标记了我的问题,因为它是关于线程控制原语的。如果标准 c++ 中没有解决方案,我愿意接受使用 Linux/POSIX 特定函数的解决方案。
假设您的供应商的标准库使用 pthread_cond_*
函数来实现 C++11 条件变量(libstdc++ 和 libc++ 这样做),pthread_cond_*
函数不是异步信号安全的,所以不能从信号处理程序调用。
来自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.
如果您习惯使用信号量,sem_post
被指定为异步信号安全。否则,您的信号处理选项是通常的:经典的自管道,阻塞在 sigwait
/sigwaitinfo
上的信号处理线程,或特定于平台的工具(Linux signalfd
, 等等).
我知道 ISO/C++11 中的信号处理程序唯一允许做的事情是读取或写入无锁原子变量或 volatile sig_atomic_t
(我相信,POSIX 稍微宽松一点,允许调用一堆系统函数)。
我想知道是否有任何方法可以唤醒正在等待条件变量的线程。 IE。类似于:
#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
}
其中至少有两个问题:
- 我相信,我不允许在信号处理程序中调用
notify_one()
(如果我错了请纠正我) - 信号可能恰好在检查
doWait
和线程进入休眠之间到达,因此它永远不会醒来(显然,我无法在 signalHander 中锁定互斥锁来避免这种情况) .
到目前为止,我能看到的唯一解决方案是在 doWait
变量上实现忙等待(可能在每次迭代中休眠几毫秒),这让我觉得效率很低。
请注意,尽管我上面的程序只有一个线程,但我用多线程标记了我的问题,因为它是关于线程控制原语的。如果标准 c++ 中没有解决方案,我愿意接受使用 Linux/POSIX 特定函数的解决方案。
假设您的供应商的标准库使用 pthread_cond_*
函数来实现 C++11 条件变量(libstdc++ 和 libc++ 这样做),pthread_cond_*
函数不是异步信号安全的,所以不能从信号处理程序调用。
来自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.
如果您习惯使用信号量,sem_post
被指定为异步信号安全。否则,您的信号处理选项是通常的:经典的自管道,阻塞在 sigwait
/sigwaitinfo
上的信号处理线程,或特定于平台的工具(Linux signalfd
, 等等).