在信号处理程序中设置标志 [英] set flag in signal handler

查看:88
本文介绍了在信号处理程序中设置标志的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 11中,对于给定的请求循环类型(作为Web请求循环的一部分),在捕获到的信号上执行不安全代码的最安全(最高效)的方法是什么?例如,从Linux命令行捕获SIGUSR1:kill -30 <process pid>

In C++11, what is the safest (and perferrably most efficient) way to execute unsafe code on a signal being caught, given a type of request-loop (as part of a web request loop)? For example, on catching a SIGUSR1 from a linux command line: kill -30 <process pid>

对于下一个被触发的请求,可以运行不安全代码",并且如果在运行不安全代码之前多次触发信号,则不会丢失任何信息.

It is acceptable for the 'unsafe code' to be run on the next request being fired, and no information is lost if the signal is fired multiple times before the unsafe code is run.

例如,我当前的代码是:

For example, my current code is:

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布尔值时可能会出现问题.

where I know there could be problems in the main loop testing+setting the globalFlag boolean.

if (globalFlag)测试将在相当紧凑的循环中运行,并且可接受偶尔"的假阴性结果.但是,我怀疑Basile Starynkevitch的解决方案还没有优化吗?

The if (globalFlag) test will be run in a fairly tight loop, and an 'occasional' false negative is acceptable. However, I suspect there's no optimisation over Basile Starynkevitch's solution anyway?

推荐答案

您应声明您的标志

  static volatile sig_atomic_t globalFlag = 0;

例如参见 sig_atomic_t

See e.g. sig_atomic_t, this question and don't forget the volatile qualifier. (It may have been spelled sigatomic_t for C).

(在Linux上)(具体而言),您可以使用 signalfd(2)来获取信号的文件描述符,并且fd可以为轮询(2)-通过事件循环.

On Linux (specifically) you could use signalfd(2) to get a filedescriptor for the signal, and that fd can be poll(2)-ed by your event loop.

某些事件循环库( libevent

Some event loop libraries (libevent, libev ...) know how to handle signals.

还有设置管道的技巧(请参见 pipe(2) pipe(7)以获得更多信息),只需 write(2)-在信号处理程序中在其上输入一些字节.事件循环将轮询并读取该管道. Qt推荐

And there is also the trick of setting up a pipe (see pipe(2) and pipe(7) for more) at initialization, and just write(2)-ing some byte on it in the signal handler. The event loop would poll and read that pipe. Such a trick is recommended by Qt.

另请阅读 signal(7)信号安全(7)(它说明了什么是信号处理程序中可用的功能或系统调用数量有限)....

Read also signal(7) and signal-safety(7) (it explains what are the limited set of functions or syscalls usable inside a signal handler)....

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

BTW, correctness is more important than efficiency. In general, you get few signals (e.g. most programs get a signal once every second at most, not every millisecond).

这篇关于在信号处理程序中设置标志的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆