Chinese Yellow Pages | Classifieds | Knowledge | Tax | IME

gdb and signal handling ( especially sigwaitinfo )

How gdb generally works

In a debugging session, when the debugger wants to set a breakpoint, it replaces an instruction by int3

When the trap instruction (0xCC on x86) is executed, the processor notifies the OS.

On UNIX, the OS checks to see whether the process is being ptraced by somebody.

  • If no, the SIGTRAP signal is delivered to the application, which usually results in process being killed (but you can catch and handle the signal in the application).
  • If there is a ptraceer (usually a debugger), then the signal is not delivered to the application. Instead, debugger’s wait is unblocked to notify the debugger that the inferior has changed state. The debugger then looks at where the inferior process stopped, discovers that it did so because of a breakpoints, and handles the situation as appropriate (let’s you examine the inferior, or resumes it if the breakpoint is conditional and current conditions don’t match, etc.)

When the target process is stopped, it could interrupt the system_call where target process/thread is waiting/running.

GDB Interrupted System Calls



then the system call may return prematurely.



For example, do not write code like this:

	sleep (10);


Instead, write this:

	int unslept = 10;
  while (unslept > 0)
    unslept = sleep (unslept);




GDB and sigwaitinfo

if we use sigwaitinfo to handle the signal in a thread, sigwaitinfo maybe interrupted ( return -1 ) when gdb ran step/next  in another thread etc.

so we need to check sigwaitinfo() the while loop:

void signal_handler_2()
    sigset_t            mask;
    siginfo_t           info;
     sigaddset(&mask, SIGQUIT);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGTERM);
     bool run = true;
    while ( run ) {
      // this sigwaitinfo could be interrupted by gdb as we are running it as thread
     if (sigwaitinfo(&mask, &info) == -1) {
            perror(“sigwaitinfo() failed”);
      switch (info.si_signo) {
          case SIGQUIT:
          case SIGINT:
          case SIGTERM:
              // info.si_pid is pid of terminated process, it is not POSIX
              printf(“a child terminated, pid = %d\n”, info.si_pid);
              run = false;
              printf(“sig recived pid = %d\n”, info.si_pid);
              run = false;

Please rate this

Leave a Reply