- if (fflags & NOTE_EXIT) {
- if (j->p == (pid_t)kev->ident && !j->anonymous) {
- /* Note that the third argument to proc_pidinfo() is a magic
- * argument for PROC_PIDT_SHORTBSDINFO. Specifically, passing 1
- * means "don't fail on a zombie PID".
- */
- struct proc_bsdshortinfo proc;
- if (job_assumes(j, proc_pidinfo(j->p, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) > 0)) {
- if (!job_assumes(j, (pid_t)proc.pbsi_ppid == getpid())) {
- /* Someone has attached to the process with ptrace().
- * There's a race here. If we determine that we are not the
- * parent process and then fail to attach a kevent to the
- * parent PID (who is probably using ptrace()), we can take
- * that as an indication that the parent exited between
- * sysctl(3) and kevent_mod(). The reparenting of the PID
- * should be atomic to us, so in that case, we reap the job
- * as normal.
- *
- * Otherwise, we wait for the death of the parent tracer and
- * then reap, just as we would if a job died while we were
- * sampling it at shutdown.
- *
- * Note that we foolishly assume that in the process *tree*
- * a node cannot be its own parent. Apparently, that is not
- * correct. If this is the case, we forsake the process to
- * its own devices. Let it reap itself.
- */
- if (!job_assumes(j, proc.pbsi_ppid != kev->ident)) {
- job_log(j, LOG_WARNING, "Job is its own parent and has (somehow) exited. Leaving it to waste away.");
- return;
- }
- if (job_assumes_zero_p(j, kevent_mod(proc.pbsi_ppid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, j)) != -1) {
- j->tracing_pid = proc.pbsi_ppid;
- j->reap_after_trace = true;
- return;
- }
- }
- }
- } else if (!j->anonymous) {
- if (j->tracing_pid == (pid_t)kev->ident) {
- job_cleanup_after_tracer(j);
-
- return;
- } else if (j->tracing_pid && !j->reap_after_trace) {
- // The job exited before our sample completed.
- job_log(j, LOG_DEBUG | LOG_CONSOLE, "Job has exited. Will reap after tracing PID %i exits.", j->tracing_pid);
- j->reap_after_trace = true;
- return;
- }
- }
- }
-