c++ 信号处理程序可以唤醒线程吗?

问题描述 投票:0回答:2

由于 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(),所以我唯一的选择是在主线程上忙等待(有或没有预定义的睡眠周期) ).

理想情况下,我希望主线程休眠直到收到信号,可能带有条件变量,但这看起来是非法的。

c++ multithreading signals
2个回答
1
投票

我建议(阻塞信号并)使用 sigwait(2) 在主线程中同步等待信号,然后你就完全避免了必须从信号处理程序到线程进行通信的问题。


0
投票

您所追求的是一种以异步信号安全的方式唤醒线程的方法。

我在 Linux 中执行此操作的首选方法是使用 POSIX 信号量。请记住,这可能无法移植到其他操作系统,因为操作系统不需要 POSIX 信号量即可被视为符合 POSIX 标准。

  1. 注册信号处理程序之前:
  // signalSemaphore is a global variable
  if (sem_init(&signalSemaphore, 0, 0)) {
    std::cerr << "Unable to initialise semaphore: " << strerror(errno);
    return 1;
  }
  1. 来自你想要唤醒的线程:
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);
  }
}
  1. 从信号处理程序中,将信号量设置为 1。这将解锁
    sem_wait()
    调用:
void signalHandler(int signal) {
  sem_post(&signalSemaphore);
}

或者,使用管道也是一种选择,因为

read()
write()
系统调用也是异步信号安全的,并且管道是一种更可移植的机制。请参阅此处有关如何执行此操作的示例:如何以异步信号安全的方式唤醒 macOS 中的线程?

© www.soinside.com 2019 - 2024. All rights reserved.