简体   繁体   English

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

[英]Propagating Signal (SIGINT) to C++11 threads

I am trying to terminate correctly my multi-threaded C++11 application upon receiving SIGINT signal ( ^C it is), but for some reason it does not propagate to child threads, though main thread responds to it well. 我试图在接收到SIGINT信号( ^C它)时正确地终止我的多线程C ++ 11应用程序,但由于某种原因它不会传播到子线程,尽管主线程很好地响应它。

For instnce (as in code sample below), if we have a some blocking function inside of thread (like sleep() ), it will take out all ^C control from you if you installed any SIGNT hooks using, say, sigaction() function. 对于instnce(如下面的代码示例中所示),如果我们在线程内部有一些阻塞函数(比如sleep() ),如果你使用sigaction()安装了任何SIGNT钩子,它将取出你的所有^C控件。功能。

Is there any way to fix- or work-around such behavior? 有没有办法解决或解决这种行为? Is there a way to propagate main-received signals to child threads? 有没有办法将主接收信号传播到子线程?

EDIT : replaced POSIX sleep() with C++11 std::this_thread::sleep_for() 编辑 :用C ++ 11替换POSIX sleep() std::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;
}

EDIT2 So the solution was to replace all blocking calls with non-blocking counterparts and such mechanisms as condition variables and polling. EDIT2所以解决方案是用非阻塞对应物和条件变量和轮询等机制替换所有阻塞调用。

The actual question remains unanswered as current software (and, possibly, hardware) is not designed in way of handling signals more then in one thread, which one is supposed to tell others what to do upon receiving signals. 实际的问题仍然没有答案,因为当前的软件(以及可能的硬件)并不是设计成在一个线程中处理信号的方式,而应该告诉其他人在接收信号时该做什么。

I am trying to terminate correctly my multi-threaded C++11 application upon receiving SIGINT signal (^C it is), but for some reason it does not propagate to child threads, though main thread responds to it well. 我试图在接收到SIGINT信号(^ C它)时正确地终止我的多线程C ++ 11应用程序,但由于某种原因它不会传播到子线程,尽管主线程很好地响应它。

POSIX distinguishes signals targeted to process or a thread . POSIX区分针对进程或线程的信号 In either case only one thread receives the signal: 在任何一种情况下,只有一个线程接收信号:

At the time of generation, a determination shall be made whether the signal has been generated for the process or for a specific thread within the process. 在生成时,应确定是为过程还是为过程中的特定线程生成了信号。 Signals which are generated by some action attributable to a particular thread, such as a hardware fault, shall be generated for the thread that caused the signal to be generated. 应该为导致生成信号的线程生成由可归因于特定线程的某些动作(例如硬件故障)生成的信号。 Signals that are generated in association with a process ID or process group ID or an asynchronous event, such as terminal activity, shall be generated for the process. 应为进程生成与进程ID或进程组ID或异步事件(例如终端活动)相关联生成的信号。

... ...

... Signals generated for the process shall be delivered to exactly one of those threads within the process which is in a call to a sigwait() function selecting that signal or has not blocked delivery of the signal. ...为该过程生成的信号应该被传递到过程中的那些线程中的一个,该线程在调用sigwait()函数中选择该信号或​​者没有阻止信号的传递。 If there are no threads in a call to a sigwait() function selecting that signal, and if all threads within the process block delivery of the signal, the signal shall remain pending on the process until a thread calls a sigwait() function selecting that signal, a thread unblocks delivery of the signal, or the action associated with the signal is set to ignore the signal. 如果在调用sigwait()函数时没有线程选择该信号,并且如果进程中的所有线程都阻塞了信号的传递,则该信号将在进程中保持挂起状态,直到线程调用sigwait()函数选择该信号为止。信号,线程解除阻塞信号的传递,或者与信号相关联的动作被设置为忽略该信号。

In a multi-threaded process a common solution is to block process signals one intends to handle in all threads but one. 在多线程进程中,常见的解决方案是阻止一个打算在除一个线程之外的所有线程中处理的进程信号。 That one thread would normally handle all process signals and tell other threads what to do (eg terminate). 那个线程通常会处理所有进程信号并告诉其他线程做什么(例如终止)。

Also, because signaled is set by the signal handler, it should be declared volatile , this is one of the two use cases volatile was introduced for: 同时,由于signaled由信号处理程序设置,它应该被宣布volatile ,这是两个用例一个volatile的介绍:

static int volatile signaled = 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM