如何取消发送信号到尚未发送的进程?
考虑我向流程发送信号的情况,但流程处于不可中断状态。
我正在进行条件等待处理信号。但由于它不是我想继续执行。在这种情况下,有没有办法可以取消发送的信号(尚未发送)
答案 0 :(得分:8)
如果在传送信号之前忽略该信号,则取消待处理信号。你只需要忽略这个信号。您可以通过将sigaction()
中的sa_handler
字段设置为struct sigaction
,使用SIG_IGN
执行此操作。
这里有一些示例代码说明了这一点,并表明它有效。代码执行以下操作:
SIGINT
,以便我们有一个时间窗口在阻止它时发送它SIGINT
- 这将生成一个待处理的SIGINT
,当进程信号掩码是更改为不包含SIGINT
的遮罩(如果忽略该信号,将被取消)。SIGINT
SIGINT
待处理后忽略SIGINT
。这具有取消待处理信号的效果。SIGINT
的原始默认操作,即终止进程SIGINT
。您可以看到该过程在步骤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;
}