title: Why does a SIGTRAP PTRACE_EVENT_STOP occur when the tracee receives SIGCONT?
body: <p>I'm using <code>PTRACE_SEIZE</code> to trace the execution of a child process, but I'm running into an issue where a non-group-stop <code>PTRACE_EVENT_STOP</code> (signal == <code>SIGTRAP</code>) is being emitted when the tracee receives a <code>SIGCONT</code>. I can't seem to find any documentation that might indicate why this is happening. From what I can gather in the <code>ptrace(2)</code> manpage, <code>PTRACE_EVENT_STOP</code> only occurs when one of the following conditions are true:</p>
  
  <ul>
  <li>The tracer called <code>ptrace(PTRACE_INTERRUPT, ...)</code></li>
  <li>The tracee entered group stop (signal is <code>SIGSTOP</code>, <code>SIGTSTP</code>, <code>SIGTTIN</code>, or <code>SIGTTOU</code>)</li>
  <li>The tracee called <code>fork</code>/<code>vfork</code>/<code>clone</code> and the tracer automatically attached to the new process/thread</li>
  </ul>
  
  <p>In the sample program below, I'm getting a <code>PTRACE_EVENT_STOP</code> with signal <code>SIGTRAP</code>, but it doesn't match any of those 3 conditions. When I run the program, I get the following output:</p>
  
  <pre><code>[Child] Raising SIGSTOP
  Event for pid 29236: Tracee entered group-stop PTRACE_EVENT_STOP (signal: 19)
  Event for pid 29236: Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: 5)
  Event for pid 29236: Tracee entered/exited syscall
  Event for pid 29236: Tracee entered/exited syscall
  Event for pid 29236: Tracee received signal (signal: 18)
  Event for pid 29236: Tracee entered/exited syscall
  [Child] Resumed from SIGSTOP
  Event for pid 29236: Tracee entered/exited syscall
  Event for pid 29236: Tracee entered/exited syscall
  Event for pid 29236: Process exited
  </code></pre>
  
  <p>Any ideas as to what this particular <code>PTRACE_EVENT_STOP</code> means?</p>
  
  <hr>
  
  <p>Sample program:</p>
  
  <pre><code>#include &lt;errno.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  
  #include &lt;sys/ptrace.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;unistd.h&gt;
  
  static void handle_events(pid_t pid_spec)
  {
      while (1) {
          int status;
          pid_t pid = waitpid(pid_spec, &amp;status, __WALL);
  
          printf("Event for pid %d: ", pid);
  
          if (WIFEXITED(status)) {
              printf("Process exited\n");
              break;
          } else if (WIFSIGNALED(status)) {
              printf("Process killed by signal\n");
              break;
          } else if (WIFSTOPPED(status)) {
              int ptrace_event = status &gt;&gt; 16;
              int signal = WSTOPSIG(status);
  
              switch (ptrace_event) {
                  case PTRACE_EVENT_STOP:
                      if (signal == SIGSTOP || signal == SIGTSTP
                              || signal == SIGTTIN || signal == SIGTTOU) {
                          printf("Tracee entered group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
                          ptrace(PTRACE_LISTEN, pid, NULL, NULL);
                      } else {
                          printf("Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
                          ptrace(PTRACE_SYSCALL, pid, NULL, 0);
                      }
                      break;
  
                  default:
                      if (signal == (SIGTRAP | 0x80)) {
                          printf("Tracee entered/exited syscall\n");
                          ptrace(PTRACE_SYSCALL, pid, NULL, 0);
                      } else {
                          printf("Tracee received signal (signal: %d)\n", signal);
                          ptrace(PTRACE_SYSCALL, pid, NULL, signal);
                      }
                      break;
              }
          }
      }
  }
  
  int main()
  {
      pid_t pid = fork();
  
      if (pid == 0) {
          printf("[Child] Raising SIGSTOP\n");
  
          // Allow parent to PTRACE_SEIZE
          if (raise(SIGSTOP) != 0) {
              _exit(255);
          }
  
          printf("[Child] Resumed from SIGSTOP\n");
          _exit(0);
      }
  
      // Wait for stop
      int status;
      waitpid(pid, &amp;status, WSTOPPED);
  
      ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACESYSGOOD);
  
      // Allow child to continue
      kill(pid, SIGCONT);
  
      handle_events(pid);
  
      return EXIT_SUCCESS;
  }
  </code></pre>
  
  <hr>
  
  <p><code>strace</code> seems to call <code>PTRACE_SYSCALL</code> whenever it sees a non-group-stop <code>PTRACE_EVENT_STOP</code>:</p>
  
  <ul>
  <li><a href="https://github.com/strace/strace/blob/b1e1eb7731e50900bb4591a3a71b96ab37e106a8/strace.c#L2360" rel="nofollow noreferrer">https://github.com/strace/strace/blob/b1e1eb7731e50900bb4591a3a71b96ab37e106a8/strace.c#L2360</a></li>
  <li><a href="https://github.com/strace/strace/blob/b1e1eb7731e50900bb4591a3a71b96ab37e106a8/strace.c#L2408-L2409" rel="nofollow noreferrer">https://github.com/strace/strace/blob/b1e1eb7731e50900bb4591a3a71b96ab37e106a8/strace.c#L2408-L2409</a></li>
  </ul>