使用select()时无法捕获SIGINT信号

时间:2009-02-26 09:22:40

标签: select signals

我为SIGINT定义了自己的信号处理程序。但是我的信号处理程序没有被调用 信号处理程序只是终止程序。但是在按ctrl + c时,程序不会退出。请帮忙......

这是代码的外观......

sa.sa_handler = handle_termsig;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
sigemptyset(&g_termsigs);
sigaddset(&g_termsigs, SIGINT);
sigaddset(&g_termsigs, SIGTERM);

sigprocmask(SIG_BLOCK, &g_termsigs, 0);
if (select (fdmax+1, &rd, &wr, NULL, &time) < 0)
{
  exit();
}
sigprocmask(SIG_UNBLOCK, &g_termsigs, &savemask);

2 个答案:

答案 0 :(得分:0)

由于在调用select时SIGINT被阻止,因此不会传递它,并且select()不会被中断。如果您的处理程序只调用exit()并且您希望在代码调用select时这样做,那么最好的解决方案就是单独保留信号掩码。如果您出于某种原因不希望在致电select()时调用普通处理程序,则可以使用pselect()函数。

编辑:

何时传递信号

如果信号已启用(即未阻止)且进程正在运行,则立即执行。

如果信号被启用并且进程在可中断的睡眠中休眠(这意味着top / ps输出中的状态== S),则系统调用被中断(例如,通过将EINTR返回给调用者)并且信号处理程序是执行。

如果信号被阻止,则一旦解除信号,它就会等待。 Syscalls不会被阻塞的信号打断。

在您的示例中,这意味着select()正在等待输入;当输入变为可用时,它返回,信号处理程序被启用(在第二次调用sigprocmask中)并且调用处理程序。

这就是它在strace中的样子:

Process 22393 attached - interrupt to quit
19:31:05.844940 select(1, [0], NULL, NULL, NULL) = 1 (in [0])
19:31:12.131431 rt_sigprocmask(SIG_UNBLOCK, [INT TERM], [INT TERM], 8) = 0
19:31:12.131560 --- SIGINT (Interrupt) @ 0 (0) ---
19:31:12.131730 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
19:31:12.131871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ffb000
19:31:12.132027 write(1, "signal..."..., 9) = 9
19:31:12.132148 exit_group(1)           = ?
Process 22393 detached

如何启用信号

要始终启用信号处理程序,只需从代码中删除对sigprocmask()的调用。

答案 1 :(得分:0)

您在SIGINT电话周围明确阻止select,因此当然不起作用。

你想做什么?