)]}'
{
  "commit": "45cb24a1da53beb70f09efccc0373f6a47a9efe0",
  "tree": "f27b2a6ca76f9b4e17f2adddfcf27b3d988152ed",
  "parents": [
    "9b84cca2564b9a5b2d064fb44d2a55a5b44473a0"
  ],
  "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: Allow access to job control events through ptracees\n\nCurrently a real parent can\u0027t access job control stopped/continued\nevents through a ptraced child.  This utterly breaks job control when\nthe children are ptraced.\n\nFor example, if a program is run from an interactive shell and then\nstrace(1) attaches to it, pressing ^Z would send SIGTSTP and strace(1)\nwould notice it but the shell has no way to tell whether the child\nentered job control stop and thus can\u0027t tell when to take over the\nterminal - leading to awkward lone ^Z on the terminal.\n\nBecause the job control and ptrace stopped states are independent,\nthere is no reason to prevent real parents from accessing the stopped\nstate regardless of ptrace.  The continued state isn\u0027t separate but\nptracers don\u0027t have any use for them as ptracees can never resume\nwithout explicit command from their ptracers, so as long as ptracers\ndon\u0027t consume it, it should be fine.\n\nAlthough this is a behavior change, because the previous behavior is\nutterly broken when viewed from real parents and the change is only\nvisible to real parents, I don\u0027t think it\u0027s necessary to make this\nbehavior optional.\n\nOne situation to be careful about is when a task from the real\nparent\u0027s group is ptracing.  The parent group is the recipient of both\nptrace and job control stop events and one stop can be reported as\nboth job control and ptrace stops.  As this can break the current\nptrace users, suppress job control stopped events for these cases.\n\nIf a real parent ptracer wants to know about both job control and\nptrace stops, it can create a separate process to serve the role of\nreal parent.\n\nNote that this only updates wait(2) side of things.  The real parent\ncan access the states via wait(2) but still is not properly notified\n(woken up and delivered signal).  Test case polls wait(2) with WNOHANG\nto work around.  Notification will be updated by future patches.\n\nTest case follows.\n\n  #include \u003cstdio.h\u003e\n  #include \u003cunistd.h\u003e\n  #include \u003ctime.h\u003e\n  #include \u003cerrno.h\u003e\n  #include \u003csys/types.h\u003e\n  #include \u003csys/ptrace.h\u003e\n  #include \u003csys/wait.h\u003e\n\n  int main(void)\n  {\n\t  const struct timespec ts100ms \u003d { .tv_nsec \u003d 100000000 };\n\t  pid_t tracee, tracer;\n\t  siginfo_t si;\n\t  int i;\n\n\t  tracee \u003d fork();\n\t  if (tracee \u003d\u003d 0) {\n\t\t  while (1) {\n\t\t\t  printf(\"tracee: SIGSTOP\\n\");\n\t\t\t  raise(SIGSTOP);\n\t\t\t  nanosleep(\u0026ts100ms, NULL);\n\t\t\t  printf(\"tracee: SIGCONT\\n\");\n\t\t\t  raise(SIGCONT);\n\t\t\t  nanosleep(\u0026ts100ms, NULL);\n\t\t  }\n\t  }\n\n\t  waitid(P_PID, tracee, \u0026si, WSTOPPED | WNOHANG | WNOWAIT);\n\n\t  tracer \u003d fork();\n\t  if (tracer \u003d\u003d 0) {\n\t\t  nanosleep(\u0026ts100ms, NULL);\n\t\t  ptrace(PTRACE_ATTACH, tracee, NULL, NULL);\n\n\t\t  for (i \u003d 0; i \u003c 11; i++) {\n\t\t\t  si.si_pid \u003d 0;\n\t\t\t  waitid(P_PID, tracee, \u0026si, WSTOPPED);\n\t\t\t  if (si.si_pid \u0026\u0026 si.si_code \u003d\u003d CLD_TRAPPED)\n\t\t\t\t  ptrace(PTRACE_CONT, tracee, NULL,\n\t\t\t\t\t (void *)(long)si.si_status);\n\t\t  }\n\t\t  printf(\"tracer: EXITING\\n\");\n\t\t  return 0;\n\t  }\n\n\t  while (1) {\n\t\t  si.si_pid \u003d 0;\n\t\t  waitid(P_PID, tracee, \u0026si,\n\t\t\t WSTOPPED | WCONTINUED | WEXITED | WNOHANG);\n\t\t  if (si.si_pid)\n\t\t\t  printf(\"mommy : WAIT status\u003d%02d code\u003d%02d\\n\",\n\t\t\t\t si.si_status, si.si_code);\n\t\t  nanosleep(\u0026ts100ms, NULL);\n\t  }\n\t  return 0;\n  }\n\nBefore the patch, while ptraced, the parent can\u0027t see any job control\nevents.\n\n  tracee: SIGSTOP\n  mommy : WAIT status\u003d19 code\u003d05\n  tracee: SIGCONT\n  tracee: SIGSTOP\n  tracee: SIGCONT\n  tracee: SIGSTOP\n  tracee: SIGCONT\n  tracee: SIGSTOP\n  tracer: EXITING\n  mommy : WAIT status\u003d19 code\u003d05\n  ^C\n\nAfter the patch,\n\n  tracee: SIGSTOP\n  mommy : WAIT status\u003d19 code\u003d05\n  tracee: SIGCONT\n  mommy : WAIT status\u003d18 code\u003d06\n  tracee: SIGSTOP\n  mommy : WAIT status\u003d19 code\u003d05\n  tracee: SIGCONT\n  mommy : WAIT status\u003d18 code\u003d06\n  tracee: SIGSTOP\n  mommy : WAIT status\u003d19 code\u003d05\n  tracee: SIGCONT\n  mommy : WAIT status\u003d18 code\u003d06\n  tracee: SIGSTOP\n  tracer: EXITING\n  mommy : WAIT status\u003d19 code\u003d05\n  ^C\n\n-v2: Oleg pointed out that wait(2) should be suppressed for the real\n     parent\u0027s group instead of only the real parent task itself.\n     Updated accordingly.\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": "84d13d6bb30b9b81102c71e711da9726e41a59b3",
      "old_mode": 33188,
      "old_path": "kernel/exit.c",
      "new_id": "1a0f10f0a4db69abd4d9c321750f218c9888d03a",
      "new_mode": 33188,
      "new_path": "kernel/exit.c"
    }
  ]
}
