)]}'
{
  "commit": "244056f9dbbc6dc4126a301c745fa3dd67d8af3c",
  "tree": "dced7105f53b5d5ed34e170d77f5c6ab0172542a",
  "parents": [
    "ceb6bd67f9b9db765e1c29405f26e8460391badd"
  ],
  "author": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Wed Mar 23 10:37:01 2011 +0100"
  },
  "committer": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Wed Mar 23 10:37:01 2011 +0100"
  },
  "message": "job control: Don\u0027t send duplicate job control stop notification while ptraced\n\nJust as group_exit_code shouldn\u0027t be generated when a PTRACE_CONT\u0027d\ntask re-enters job control stop, notifiction for the event should be\nsuppressed too.  The logic is the same as the group_exit_code\ngeneration suppression in do_signal_stop(), if SIGNAL_STOP_STOPPED is\nalready set, the task is re-entering job control stop without\nintervening SIGCONT and the notifications should be suppressed.\n\nTest case follows.\n\n  #include \u003cstdio.h\u003e\n  #include \u003cunistd.h\u003e\n  #include \u003csignal.h\u003e\n  #include \u003ctime.h\u003e\n  #include \u003csys/ptrace.h\u003e\n  #include \u003csys/wait.h\u003e\n\n  static const struct timespec ts100ms \u003d { .tv_nsec \u003d 100000000 };\n  static pid_t tracee, tracer;\n\n  static const char *pid_who(pid_t pid)\n  {\n\t  return pid \u003d\u003d tracee ? \"tracee\" : (pid \u003d\u003d tracer ? \"tracer\" : \"mommy \");\n  }\n\n  static void sigchld_sigaction(int signo, siginfo_t *si, void *ucxt)\n  {\n\t  printf(\"%s: SIG status\u003d%02d code\u003d%02d (%s)\\n\",\n\t\t pid_who(getpid()), si-\u003esi_status, si-\u003esi_code,\n\t\t pid_who(si-\u003esi_pid));\n  }\n\n  int main(void)\n  {\n\t  const struct sigaction chld_sa \u003d { .sa_sigaction \u003d sigchld_sigaction,\n\t\t\t\t\t     .sa_flags \u003d SA_SIGINFO|SA_RESTART };\n\t  siginfo_t si;\n\n\t  sigaction(SIGCHLD, \u0026chld_sa, NULL);\n\n\t  tracee \u003d fork();\n\t  if (!tracee) {\n\t\t  tracee \u003d getpid();\n\t\t  while (1)\n\t\t\t  pause();\n\t  }\n\n\t  kill(tracee, SIGSTOP);\n\t  waitid(P_PID, tracee, \u0026si, WSTOPPED);\n\n\t  tracer \u003d fork();\n\t  if (!tracer) {\n\t\t  tracer \u003d getpid();\n\t\t  ptrace(PTRACE_ATTACH, tracee, NULL, NULL);\n\t\t  waitid(P_PID, tracee, \u0026si, WSTOPPED);\n\t\t  ptrace(PTRACE_CONT, tracee, NULL, (void *)(long)si.si_status);\n\t\t  waitid(P_PID, tracee, \u0026si, WSTOPPED);\n\t\t  ptrace(PTRACE_CONT, tracee, NULL, (void *)(long)si.si_status);\n\t\t  waitid(P_PID, tracee, \u0026si, WSTOPPED);\n\t\t  printf(\"tracer: detaching\\n\");\n\t\t  ptrace(PTRACE_DETACH, tracee, NULL, NULL);\n\t\t  return 0;\n\t  }\n\n\t  while (1)\n\t\t  pause();\n\t  return 0;\n  }\n\nBefore the patch, the parent gets the second notification for the\ntracee after the tracer detaches.  si_status is zero because\ngroup_exit_code is not set by the group stop completion which\ntriggered this notification.\n\n  mommy : SIG status\u003d19 code\u003d05 (tracee)\n  tracer: SIG status\u003d00 code\u003d05 (tracee)\n  tracer: SIG status\u003d19 code\u003d04 (tracee)\n  tracer: SIG status\u003d00 code\u003d05 (tracee)\n  tracer: detaching\n  mommy : SIG status\u003d00 code\u003d05 (tracee)\n  mommy : SIG status\u003d00 code\u003d01 (tracer)\n  ^C\n\nAfter the patch, the duplicate notification is gone.\n\n  mommy : SIG status\u003d19 code\u003d05 (tracee)\n  tracer: SIG status\u003d00 code\u003d05 (tracee)\n  tracer: SIG status\u003d19 code\u003d04 (tracee)\n  tracer: SIG status\u003d00 code\u003d05 (tracee)\n  tracer: detaching\n  mommy : SIG status\u003d00 code\u003d01 (tracer)\n  ^C\n\nSigned-off-by: Tejun Heo \u003ctj@kernel.org\u003e\nAcked-by: Oleg Nesterov \u003coleg@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "f65403da4101c173a3e21df0b804ff5ad6a89262",
      "old_mode": 33188,
      "old_path": "kernel/signal.c",
      "new_id": "f799a054f292488190360c02e6ff0d0f93cabd91",
      "new_mode": 33188,
      "new_path": "kernel/signal.c"
    }
  ]
}
