如何取消待处理的信号?

时间:2015-06-08 10:30:14

标签: linux signals

如何取消发送信号到尚未发送的进程?

考虑我向流程发送信号的情况,但流程处于不可中断状态。

我正在进行条件等待处理信号。但由于它不是我想继续执行。在这种情况下,有没有办法可以取消发送的信号(尚未发送)

1 个答案:

答案 0 :(得分:8)

如果在传送信号之前忽略该信号,则取消待处理信号。你只需要忽略这个信号。您可以通过将sigaction()中的sa_handler字段设置为struct sigaction,使用SIG_IGN执行此操作。

这里有一些示例代码说明了这一点,并表明它有效。代码执行以下操作:

  1. 阻止SIGINT,以便我们有一个时间窗口在阻止它时发送它SIGINT - 这将生成一个待处理的SIGINT,当进程信号掩码是更改为不包含SIGINT的遮罩(如果忽略该信号,将被取消)。
  2. 等待您发送SIGINT
  3. 知道SIGINT待处理后忽略SIGINT。这具有取消待处理信号的效果。
  4. 恢复SIGINT的原始默认操作,即终止进程
  5. 恢复原始过程信号掩码,该掩码不会阻止SIGINT
  6. 等待你输入任何要终止的角色。
  7. 您可以看到该过程在步骤5之后没有终止并等待您的输入,这意味着待处理的信号被取消。

    以下代码说明了这一点:

    #include <signal.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    int main(void) {
    
        sigset_t block_sigint, prev_mask;
        sigemptyset(&block_sigint);
        sigaddset(&block_sigint, SIGINT);
    
        if (sigprocmask(SIG_SETMASK, &block_sigint, &prev_mask) < 0) {
            perror("Couldn't block SIGINT");
            return 0;
        }
    
        printf("SIGINT blocked: kill -SIGINT %ld to generate a pending SIGINT. Press return when done.\n", (long) getpid());
    
        /* Now, open a new terminal and send SIGINT to this process.
         *
         * After doing that, the signal will be pending delivery because it is currently blocked.
         *
         * Now, if we ignore SIGINT, the pending signal will be cancelled
         */
    
        getchar();
    
        struct sigaction ign_sigint, prev;
        ign_sigint.sa_handler = SIG_IGN;
        ign_sigint.sa_flags = 0;
        sigemptyset(&ign_sigint.sa_mask);
    
        if (sigaction(SIGINT, &ign_sigint, &prev) < 0) {
            perror("Couldn't ignore SIGINT");
            return 0;
        }
    
        printf("SIGINT ignored - pending SIGINT was canceled.\n");
    
        /* Now, restore the default action for SIGINT */
        if (sigaction(SIGINT, &prev, NULL) < 0) {
            perror("Couldn't restore default SIGINT behavior");
            return 0;
        }
    
        /* And also restore the process's original sigmask, which does not block SIGINT */
        if (sigprocmask(SIG_SETMASK, &prev_mask, NULL) < 0) {
            perror("Couldn't restore original process sigmask");
            return 0;
        }
    
        printf("Process sigmask and action for SIGINT are now restored\n");
    
        /* We will not receive SIGINT at this point because it was canceled
         * So the process will block on getchar() here instead of terminating
         */
        getchar();
    
        return 0;   
    }