问题描述
我试图在接收到SIGINT信号( ^ C
)时正确终止我的多线程C ++ 11应用程序,但由于某种原因它不会传播
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.
对于instnce(如下面的代码示例),如果我们在线程中有一个阻塞函数(如 sleep()
),它会取出你所有的 ^ C
控制如果你安装了任何SIGNT钩子, sigaction()
函数。
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.
有没有办法修复或解决此类行为?
EDIT :替换POSIX sleep()
与C ++ 11 std :: this_thread :: sleep_for()
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()
EDIT2
用非阻塞对应方法替换所有阻塞调用,以及诸如条件变量和轮询等机制。
#include <iostream>#include <thread>#include <chrono>#include <signal.h> // for sigaction() functionstatic 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;}
实际的问题仍然是未解决的,因为当前的软件
EDIT2So the solution was to replace all blocking calls with non-blocking counterparts and such mechanisms as condition variables and polling.
推荐答案
我试图在接收到SIGINT信号(^ C它是)时正确终止我的多线程C ++ 11应用程序,但由于某种原因它不会传播到子线程,虽然主线程
。在任一情况下,只有一个线程接收到信号:
POSIX distinguishes signals targeted to process or a thread. In either case only one thread receives the signal:
...
...为进程生成的信号必须传递到进程中的其中一个线程是在调用sigwait()函数选择该信号或尚未阻止信号的传递。如果在调用sigwait()函数选择该信号时没有线程,并且如果进程内的所有线程阻塞信号的传递,则该信号将保持在进程上等待,直到线程调用sigwait()函数选择信号,线程解除阻塞信号的传递或者与信号相关联的动作被设置为忽略该信号。
... 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. 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.
线程过程的一个常见的解决方案是阻止过程信号,一个打算在所有线程中处理一个。一个线程通常会处理所有的进程信号,并告诉其他线程要做什么(例如终止)。
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 (e.g. terminate).
此外,因为 $ c>由信号处理程序设置,应该声明
volatile
,这是两个用例之一 volatile
介绍了:
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:
static int volatile signaled = 0;
这篇关于传播信号(SIGINT)到C ++ 11线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!