重新注册信号处理程序会导致无限循环

时间:2018-01-13 22:33:04

标签: c signals posix infinite-loop sigint

使用以下信号处理程序,按Ctrl-C会导致重复调用处理程序,并且我不知道原因:

(警告:如果您输入Ctrl-C,则必须使用kill <pid>退出该计划。

static void handler(int sig) {
        // do something interesting

        // write so I can see if I'm in an infinite loop
        write(1, "A", 1);

        // raise normal signal behavior
        // this ensures normal signal behavior
        // for example, exiting with code 130 if Ctrl-C is used
        signal(sig, SIG_DFL);
        raise(sig);

        // re-register handler
        // that way, if signal doesn't exit the program and the signal
        //   is sent again in the future, this handler will run again
        signal(sig, handler);
}

所以我知道我对信号处理程序一无所知。我假设只有SIGCONT才能进入最后一行,因为SIGINT(例如),当它以默认行为引发时SIG_DFL )应退出而不退货。

我也知道我可以在if语句中包含最后一行只为SIGCONT包含它,但我真的想知道为什么它不像我期望的那样表现。

问题(S)

  1. 为什么在无限循环中调用信号处理程序?
  2. 我如何拥有一个有趣的处理程序,调用默认行为,然后在默认行为不退出程序的情况下重新注册自己?
  3. MCVE

    这可以通过将其写入文件sigtest.c并执行make sigtest来运行。使用Ctrl-C引发SIGINT,在另一个终端中,准备好ps | grep sigtest然后kill <pid>

    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    static void handler(int sig) {
            // do something interesting
    
            // write so I can see if I'm in an infinite loop
            write(1, "A", 1);
    
            // raise normal signal behavior
            // this ensures normal signal behavior
            // for example, exiting with code 130 if Ctrl-C is used
            signal(sig, SIG_DFL);
            raise(sig);
    
            // re-register handler
            // that way, if signal doesn't exit the program and the signal
            //   is sent again in the future, this handler will run again
            signal(sig, handler);
    }
    
    int main(void) {
            char c;
            signal(SIGINT, handler);
            signal(SIGTSTP, handler);
            signal(SIGCONT, handler);
            printf("type 'x' and 'Enter' to exit\n");
            while (1) {
                    c = getchar();
                    printf("got char: %c\n", c);
                    if (c == 'x') { break; }
            }
    }
    

1 个答案:

答案 0 :(得分:0)

我消失了,忘记了信号在被处理时被阻止了。这意味着SIGINT不会“实际被引发,直到处理程序返回之后,以及我将操作从SIG_DFL设置回我的自定义处理程序之后。因此,它是循环的。

我的示例的工作处理程序如下所示:

static void handler(int sig) {
        if (sig == SIGCONT) {
                // do something interesting
                signal(sig, handler);
                signal(SIGTSTP, handler);
        } else {
                // do something else interesting
                signal(sig, SIG_DFL);
                raise(sig);
        }
}