c++信号处理程序可以唤醒线程
c++ signal handler can wake a thread?
由于c++信号处理程序应该只访问volatile std::sig_atomic_t或std::atomic(自c++ 11起),是否有可能让线程休眠并唤醒它?
std::atomic_bool exit_now(false);
void signal_handler(int signal)
{
exit_now=true;
}
int main() {
std::signal(SIGINT, signal_handler);
A a;
B b;
a.RunAsync();
b.RunAsync();
while(!exit_now)
std::this_thread::sleep_for(std::chrono::seconds(1));
a.Stop();
b.Stop();
return 0;
}
在这种情况下,A和B::RunAsync()都在其他线程上做它们的业务,直到我调用::Stop(),所以我唯一的选择是在主线程上忙等待(有或没有预定义的睡眠周期)。
理想情况下,我希望主线程在发出信号之前一直休眠,可能会使用条件变量,但这样做看起来是非法的。
我建议(阻塞信号和)使用sigwait(2)在主线程中同步等待信号,然后您完全规避了必须从信号处理程序到线程进行通信的问题。
您需要的是一种以异步信号安全的方式唤醒线程的方法。
在Linux中,我更喜欢的方法是使用POSIX信号量。请记住,这可能无法移植到其他操作系统,因为操作系统不需要POSIX信号量才能被认为是POSIX兼容的。- 在注册信号处理器之前:
// signalSemaphore is a global variable
if (sem_init(&signalSemaphore, 0, 0)) {
std::cerr << "Unable to initialise semaphore: " << strerror(errno);
return 1;
}
- 从你想要唤醒的线程:
- 从信号处理程序,将信号量调到1。这将解锁
sem_wait()
调用:
while(sem_wait(signalSemaphore)) {
if(errno != EINTR) {
// call can be interrupted, so if the error is EINTR we ignore it
std::cerr << "Error waiting for signal semaphore: " << strerror(errno);
}
}
void signalHandler(int signal) {
sem_post(&signalSemaphore);
}
或者,使用管道也是一种选择,因为read()
和write()
系统调用也是异步信号安全的,管道是一种更可移植的机制。这里有一个关于如何做到这一点的例子:我如何以一种异步信号安全的方式唤醒macOS中的线程?
相关文章:
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 如果我们使用 notify_one() 来唤醒线程,我们还需要 yield() - C++?
- 唤醒多个线程以在每个条件下工作一次
- 视频在唤醒其他线程时输入设备断开连接
- 线程启动延迟 - 通知所有未唤醒所有线程
- 使用 Poco:Condition 唤醒两个线程
- std::condition_variable::notify_one() 不会唤醒等待线程
- 唤醒线程很耗时
- 如何定期唤醒 C++ 11 线程
- 我可以"force"线程唤醒吗?
- pthread_cond_wait唤醒多线程示例
- 如何唤醒从另一个线程选择没有超时时间的呼叫
- Boost::线程 / C++11 std::thread,想要唤醒工作线程的条件
- 固定到内核的 FIFO 线程上的 std::p romise::set_value 不会唤醒 std::future
- 在特定时间后唤醒线程
- c++信号处理程序可以唤醒线程
- c++ Windows在等待中强制唤醒线程
- 正在从信号处理程序唤醒线程
- 在不使用条件变量的情况下唤醒线程的最快方法