信号处理程序每​​次重置

时间:2019-01-05 10:13:53

标签: signals

我正在编写一个执行以下操作的C程序:

监视向其发送的信号。计算已发送SIGUSR1和SIGUSR2的次数。在发送SIGTERM时终止,但先打印出发送SIGUSR1和SIGUSR2的次数。

请注意,这是课堂上的问题,因此仅用于测试我们,实际上并没有任何用途。另外,除了上述三个信号外,不会发送其他信号。

这就是我得到的:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int sigUsr1Count = 0;
int sigUsr2Count = 0;

static void sighandler(int signum){
    switch(signum){
        case SIGUSR1:
            sigUsr1Count++;
            break;
        case SIGUSR2:
            sigUsr2Count++;
            break;
        case SIGTERM:
            printf("%d %d\n", sigUsr1Count, sigUsr2Count);
            exit(0);
    }
}

int main(int argc, char ** argv){
    pid_t mypid = getpid();
    fprintf(stderr, "My PID is %d\n", mypid);

    struct sigaction sa;
    sa.sa_flags = 0; 
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = sighandler;
    iAssert(-1 != sigaction(SIGUSR1, &sa, NULL), "sigaction1 failed");
    iAssert(-1 != sigaction(SIGUSR2, &sa, NULL), "sigaction1 failed");
    iAssert(-1 != sigaction(SIGTERM, &sa, NULL), "sigaction1 failed");

    while(true){
        fprintf(stderr, "Waiting...\n");
        sleep(3);
    }

    return 0;
}

我在某个论坛上读过某个地方,在使用sigaction时,除非将sa_flags字段设置为SA_RESETHAND,否则信号处理程序将不会重置为默认值。但是,我似乎并非如此。 (手册页描述了SA_RESETHAND标志,但是在省略该标志的情况下并未明确说明该操作。)

当我运行程序时,它只会在第一次发送SIGUSR1或SIGUSR2时转到我的处理程序,此后程序会终止并显示以下消息:

User defined signal 1 (or 2)

从这种意义上说,程序仅在以下情况之一才输出正确的值:SIGUSR1和SIGUSR2完全没有发送,或者它们每个都最多发送了一次。

iAssert宏和功能:

#define iAssert(cond, msg) crash(cond, msg, __LINE__)
void crash(bool cond, char * msg, int line){
    if(!cond){
        perror(msg);
        fprintf(stderr, "at line %d\n", line);
        exit(EXIT_FAILURE);
    }
}

我已经尝试过的编译方法(每个方法都相同):

gcc 1.c
gcc -std=c99 1.c
gcc -std=c11 1.c

有什么想法吗?

谢谢。

1 个答案:

答案 0 :(得分:-1)

既然所有评论都被证明同样无用(无罪),所以我决定采用另一种方法。

我使用了sigaction系统调用,而不是signal。我还修改了其他一些内容。由于printf不是信号安全函数,因此我引入了一个名为shouldStop的全局变量,该变量默认设置为false,然后用{{1 }}处理程序。然后在true函数内部进行打印。

代码如下:

SIGTERM

它可以按我想要的方式很好地工作。

还是谢谢。