gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 18:37:54 25 4
gpt4 key购买 nike

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

例如(如下面的代码示例),如果我们在线程内部有一些阻塞函数(如sleep()),它将取出所有^C 如果您使用 sigaction() 函数安装任何 SIGNT Hook ,则由您控制。

有什么方法可以修复或解决此类行为?有没有办法将主接收信号传播到子线程?

编辑:将 POSIX sleep() 替换为 C++11 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;
}

编辑2因此解决方案是将所有阻塞调用替换为非阻塞调用以及条件变量和轮询等机制。

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

最佳答案

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.

POSIX distinguishes signals targeted to process or a thread .在任何一种情况下,只有一个线程接收到信号:

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.

...

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

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

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

static int volatile signaled = 0;

关于c++ - 将信号 (SIGINT) 传播到 C++11 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15658016/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com