gpt4 book ai didi

c++ - 在信号处理程序中设置标志

转载 作者:太空狗 更新时间:2023-10-29 20:26:41 24 4
gpt4 key购买 nike

在 C++11 中,在给定一种请求循环(作为 Web 请求循环的一部分)的情况下,什么是最安全(最好是最有效)的方式来对被捕获的信号执行不安全代码?例如,从 linux 命令行捕获 SIGUSR1:kill -30 <process pid>

“不安全代码”在下一个请求被触发时运行是可以接受的,如果在不安全代码运行之前信号被多次触发,则不会丢失任何信息。

比如我现在的代码是:

static bool globalFlag = false;

void signalHandler(int sig_num, siginfo_t * info, void * context) {
globalFlag = true;
}
void doUnsafeThings() {
// thigns like std::vector push_back, new char[1024], set global vars, etc.
}
void doRegularThings() {
// read filesystem, read global variables, etc.
}

void main(void) {

// set up signal handler (for SIGUSR1) ...
struct sigaction sigact;
sigact.sa_sigaction = onSyncSignal;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGUSR1, &sigact, (struct sigaction *)NULL);

// main loop ...
while(acceptMoreRequests()) { // blocks until new request received
if (globalFlag) {
globalFlag = false;
doUnsafeThings();
}
doRegularThings();
}
}

我知道在主循环测试+设置 globalFlag bool 值时可能存在问题。

编辑:if (globalFlag)测试将在一个相当紧密的循环中运行,并且“偶尔”的假阴性是可以接受的。但是,我怀疑 Basile Starynkevitch 的解决方案无论如何都没有优化?

最佳答案

你应该声明你的旗帜

  static volatile sig_atomic_t globalFlag = 0;

参见例如sig_atomic_t , this question并且不要忘记 volatile 限定符。 (对于 C,它可能拼写为 sigatomic_t)。

在 Linux 上(特别是)你可以使用 signalfd(2)获取信号的文件描述符,fd 可以是 poll(2) - 由您的事件循环编辑。

一些事件循环库(libeventlibev ...)知道如何处理信号。

还有在初始化时设置管道的技巧(更多信息请参见pipe(2)pipe(7)),以及write(2) - 在信号处理程序中对它进行一些字节处理。事件循环将轮询并读取该管道。这样的技巧是recommended by Qt .

另请阅读 signal(7)signal-safety(7) (它解释了在信号处理程序中可用的一组有限的函数或系统调用)...

顺便说一句,正确性比效率更重要。通常,您收到的信号很少(例如,大多数程序最多每秒收到一次信号,而不是每毫秒收到一次)。

关于c++ - 在信号处理程序中设置标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18907477/

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