将信号(SIGINT)传播到C++ 11线程

Ale*_*min 7 c++ multithreading signals c++11

我试图在收到SIGINT信号时正确地终止我的多线程C++ 11应用程序(^C它是),但由于某种原因它不会传播到子线程,尽管主线程很好地响应它.

对于instnce(如下面的代码示例中所示),如果我们在线程内部有一些阻塞函数(例如sleep()),^C如果你使用比如安装任何SIGNT钩子,它将取消你的所有控制权sigaction().

有没有办法解决或解决这种行为?有没有办法将主接收信号传播到子线程?

编辑:sleep()用C++ 11 替换POSIXstd::this_thread::sleep_for()

#include <iostream>
#include <thread>
#include <chrono>
#include <signal.h> // for sigaction() function 

static int signaled = 0;

void threaded_foo() {
  while (!signaled) {
    // pressing ^C now will not lead to correct termination, because we are
    // sleeping for a long time (100500 seconds) and do not respond to
    // SIGINT for some tricky reason i am looking a bypassage for.
    std::chrono::seconds duration(100500);
    std::this_thread::sleep_for(duration);
  }
  std::cout << "Correct termination\n";
}

void sighandler(int sig, siginfo_t *siginfo, void *context) {
  signaled = 1;
}

void install_sig_hooks() {
  struct sigaction action;
  memset(&action, 0, sizeof(struct sigaction));
  action.sa_sigaction = sighandler;
  action.sa_flags     = SA_SIGINFO;
  sigaction(SIGINT, &action, NULL);
}

int main(int argc, char **argv) {
  install_sig_hooks();

  std::thread t(threaded_foo);
  t.join();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

EDIT2 所以解决方案是用非阻塞对应物和条件变量和轮询等机制替换所有阻塞调用.

实际的问题仍然没有答案,因为当前的软件(以及可能的硬件)并不是设计成在一个线程中处理信号的方式,而应该告诉其他人在接收信号时该做什么.

Max*_*kin 5

我试图在收到 SIGINT 信号(^C )后正确终止我的多线程 C++11 应用程序,但由于某种原因它不会传播到子线程,尽管主线程对其响应良好。

POSIX 区分针对进程或线程的信号。在任何一种情况下,只有一个线程接收信号:

在生成时,应确定是否为进程或进程内的特定线程生成了信号。由特定线程的某些操作(例如硬件故障)生成的信号应为导致生成信号的线程生成。应当为进程生成与进程 ID 或进程组 ID 或异步事件(例如终端活动)相关的信号。

...

...为进程生成的信号应准确地传递到进程中调用 sigwait() 函数选择该信号或​​尚未阻止信号传递的线程之一。如果在调用 sigwait() 函数时没有线程选择该信号,并且进程中的所有线程都阻止信号的传递,则该信号应在进程上保持挂起状态,直到有线程调用选择该信号的 sigwait() 函数。信号、线程取消阻止信号的传递,或者与信号关联的操作设置为忽略该信号。

在多线程进程中,一种常见的解决方案是阻止要在除一个线程之外的所有线程中处理的进程信号。该线程通常会处理所有进程信号并告诉其他线程要做什么(例如终止)。

另外,因为signaled是由信号处理程序设置的,所以应该声明它,这是引入的volatile两个用例之一:volatile

static int volatile signaled = 0;
Run Code Online (Sandbox Code Playgroud)