GDB、信号和 SIG_IGN
GDB, signals and SIG_IGN
将信号处理程序设置为 SIG_IGN
会在正常 运行 程序时忽略信号,但在通过 gdb 运行 时不会。
我正在使用 timer_create
和 timer_settime
函数创建一个计时器。我不想使用信号处理程序(即函数)来处理此计时器生成的信号。我决定使用 sigwait
并等待 SIGALRM
。我将 SIGALRM
的处理程序设置为 SIG_IGN
并使用 sigwait
。
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#define TRUE 1
#define ISTRUE(x) (x != 0)
#define bool int
int main() {
struct itimerspec timer_spec;
struct sigevent sig_event;
timer_t timer_id;
sigset_t sig_set;
timer_spec.it_interval.tv_sec = 1;
timer_spec.it_interval.tv_nsec = 0;
timer_spec.it_value.tv_sec = 1;
timer_spec.it_value.tv_nsec = 0;
sig_event.sigev_signo = SIGALRM;
sig_event.sigev_notify = SIGEV_SIGNAL;
signal(SIGINT, SIG_IGN);
signal(SIGALRM, SIG_IGN);
/* Create the timer */
timer_create(CLOCK_REALTIME, &sig_event, &timer_id);
timer_settime(timer_id, 0, &timer_spec, NULL);
sigemptyset(&sig_set);
sigaddset(&sig_set, SIGALRM);
int signal = 0;
bool running = TRUE;
while (ISTRUE(running)) {
sigwait(&sig_set, &signal);
switch(signal){
case SIGINT:
printf("Interrupt received.. exiting\n");
running = 0;
break;
case SIGALRM:
printf("Ticked\n");
break;
}
printf("Sleeping\n");
}
return 0;
}
在我的 IDE (CLion) 中调试应用程序以及使用 shell 中的 gdb 时,程序按预期运行。 SIGALRM
没有被忽视,这让我相信我所做的是正确的。但是,运行应用正常,sigwait
从来没有returns。
我后来意识到这是因为信号被忽略了,我需要阻止信号(使用 sigprocmask
或类似的方法)并将其设置为挂起状态。
为什么调试的时候信号能通过?这应该发生吗?我错过了什么?
您应该查看 handle
gdb 命令:
(gdb) handle SIGALRM
Signal Stop Print Pass to program Description
SIGALRM No No Yes Alarm clock
(gdb) handle SIGALRM ignore
Signal Stop Print Pass to program Description
SIGALRM No No No Alarm clock
(gdb) help handle
... read it ;-) ...
如 ptrace(2)
(gdb
使用)的联机帮助页中所述:
While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored.
将信号处理程序设置为 SIG_IGN
会在正常 运行 程序时忽略信号,但在通过 gdb 运行 时不会。
我正在使用 timer_create
和 timer_settime
函数创建一个计时器。我不想使用信号处理程序(即函数)来处理此计时器生成的信号。我决定使用 sigwait
并等待 SIGALRM
。我将 SIGALRM
的处理程序设置为 SIG_IGN
并使用 sigwait
。
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#define TRUE 1
#define ISTRUE(x) (x != 0)
#define bool int
int main() {
struct itimerspec timer_spec;
struct sigevent sig_event;
timer_t timer_id;
sigset_t sig_set;
timer_spec.it_interval.tv_sec = 1;
timer_spec.it_interval.tv_nsec = 0;
timer_spec.it_value.tv_sec = 1;
timer_spec.it_value.tv_nsec = 0;
sig_event.sigev_signo = SIGALRM;
sig_event.sigev_notify = SIGEV_SIGNAL;
signal(SIGINT, SIG_IGN);
signal(SIGALRM, SIG_IGN);
/* Create the timer */
timer_create(CLOCK_REALTIME, &sig_event, &timer_id);
timer_settime(timer_id, 0, &timer_spec, NULL);
sigemptyset(&sig_set);
sigaddset(&sig_set, SIGALRM);
int signal = 0;
bool running = TRUE;
while (ISTRUE(running)) {
sigwait(&sig_set, &signal);
switch(signal){
case SIGINT:
printf("Interrupt received.. exiting\n");
running = 0;
break;
case SIGALRM:
printf("Ticked\n");
break;
}
printf("Sleeping\n");
}
return 0;
}
在我的 IDE (CLion) 中调试应用程序以及使用 shell 中的 gdb 时,程序按预期运行。 SIGALRM
没有被忽视,这让我相信我所做的是正确的。但是,运行应用正常,sigwait
从来没有returns。
我后来意识到这是因为信号被忽略了,我需要阻止信号(使用 sigprocmask
或类似的方法)并将其设置为挂起状态。
为什么调试的时候信号能通过?这应该发生吗?我错过了什么?
您应该查看 handle
gdb 命令:
(gdb) handle SIGALRM
Signal Stop Print Pass to program Description
SIGALRM No No Yes Alarm clock
(gdb) handle SIGALRM ignore
Signal Stop Print Pass to program Description
SIGALRM No No No Alarm clock
(gdb) help handle
... read it ;-) ...
如 ptrace(2)
(gdb
使用)的联机帮助页中所述:
While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored.