From owner-svn-src-all@freebsd.org Sat Jul 18 09:02:58 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 494E19A5667; Sat, 18 Jul 2015 09:02:58 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2D1A61FD5; Sat, 18 Jul 2015 09:02:58 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t6I92wl5079733; Sat, 18 Jul 2015 09:02:58 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t6I92pg2079712; Sat, 18 Jul 2015 09:02:51 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201507180902.t6I92pg2079712@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Sat, 18 Jul 2015 09:02:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285670 - in head: lib/libc/sys lib/libkvm sys/compat/cloudabi sys/compat/linux sys/compat/svr4 sys/fs/procfs sys/kern sys/sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 18 Jul 2015 09:02:58 -0000 Author: kib Date: Sat Jul 18 09:02:50 2015 New Revision: 285670 URL: https://svnweb.freebsd.org/changeset/base/285670 Log: The si_status field of the siginfo_t, provided by the waitid(2) and SIGCHLD signal, should keep full 32 bits of the status passed to the _exit(2). Split the combined p_xstat of the struct proc into the separate exit status p_xexit for normal process exit, and signalled termination information p_xsig. Kernel-visible macro KW_EXITCODE() reconstructs old p_xstat from p_xexit and p_xsig. p_xexit contains complete status and copied out into si_status. Requested by: Joerg Schilling Reviewed by: jilles (previous version), pho Tested by: pho Sponsored by: The FreeBSD Foundation Modified: head/lib/libc/sys/wait.2 head/lib/libkvm/kvm_proc.c head/sys/compat/cloudabi/cloudabi_proc.c head/sys/compat/linux/linux_fork.c head/sys/compat/linux/linux_misc.c head/sys/compat/svr4/svr4_misc.c head/sys/fs/procfs/procfs_ctl.c head/sys/fs/procfs/procfs_ioctl.c head/sys/kern/kern_event.c head/sys/kern/kern_exec.c head/sys/kern/kern_exit.c head/sys/kern/kern_kthread.c head/sys/kern/kern_proc.c head/sys/kern/kern_sig.c head/sys/kern/sys_procdesc.c head/sys/kern/sys_process.c head/sys/sys/proc.h head/sys/sys/wait.h Modified: head/lib/libc/sys/wait.2 ============================================================================== --- head/lib/libc/sys/wait.2 Sat Jul 18 06:48:30 2015 (r285669) +++ head/lib/libc/sys/wait.2 Sat Jul 18 09:02:50 2015 (r285670) @@ -362,6 +362,15 @@ field set to and the .Fa si_pid field set to the process ID of the process reporting status. +For the exited process, the +.Fa si_status +field of the +.Dv siginfo_t +structure contains the full 32 bit exit status passed to +.Xr _exit 2 ; +the +.Fa status +argument of other calls only returns 8 lowest bits of the exit status. .Pp When the .Dv WNOHANG @@ -656,13 +665,6 @@ is an extension; .Tn POSIX only permits this flag with .Fn waitid . -.Pp -.Tn POSIX -requires -.Fn waitid -to return the full 32 bits passed to -.Xr _exit 2 ; -this implementation only returns 8 bits like the other calls. .Sh HISTORY The .Fn wait Modified: head/lib/libkvm/kvm_proc.c ============================================================================== --- head/lib/libkvm/kvm_proc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/lib/libkvm/kvm_proc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_KW_EXITCODE +#include #include #include #include @@ -389,7 +391,7 @@ nopgrp: kp->ki_siglist = proc.p_siglist; SIGSETOR(kp->ki_siglist, mtd.td_siglist); kp->ki_sigmask = mtd.td_sigmask; - kp->ki_xstat = proc.p_xstat; + kp->ki_xstat = KW_EXITCODE(proc.p_xexit, proc.p_xsig); kp->ki_acflag = proc.p_acflag; kp->ki_lock = proc.p_lock; if (proc.p_state != PRS_ZOMBIE) { Modified: head/sys/compat/cloudabi/cloudabi_proc.c ============================================================================== --- head/sys/compat/cloudabi/cloudabi_proc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/compat/cloudabi/cloudabi_proc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -57,7 +57,7 @@ cloudabi_sys_proc_exit(struct thread *td struct cloudabi_sys_proc_exit_args *uap) { - exit1(td, W_EXITCODE(uap->rval, 0)); + exit1(td, uap->rval, 0); /* NOTREACHED */ } Modified: head/sys/compat/linux/linux_fork.c ============================================================================== --- head/sys/compat/linux/linux_fork.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/compat/linux/linux_fork.c Sat Jul 18 09:02:50 2015 (r285670) @@ -398,7 +398,7 @@ linux_exit(struct thread *td, struct lin * exit via pthread_exit() try thr_exit() first. */ kern_thr_exit(td); - exit1(td, W_EXITCODE(args->rval, 0)); + exit1(td, args->rval, 0); /* NOTREACHED */ } Modified: head/sys/compat/linux/linux_misc.c ============================================================================== --- head/sys/compat/linux/linux_misc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/compat/linux/linux_misc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -1839,7 +1839,7 @@ linux_exit_group(struct thread *td, stru * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?) * as it doesnt occur often. */ - exit1(td, W_EXITCODE(args->error_code, 0)); + exit1(td, args->error_code, 0); /* NOTREACHED */ } Modified: head/sys/compat/svr4/svr4_misc.c ============================================================================== --- head/sys/compat/svr4/svr4_misc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/compat/svr4/svr4_misc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -1277,7 +1277,7 @@ loop: /* Found a zombie, so cache info in local variables. */ pid = p->p_pid; - status = p->p_xstat; + status = KW_EXITCODE(p->p_xexit, p->p_xsig); ru = p->p_ru; PROC_STATLOCK(p); calcru(p, &ru.ru_utime, &ru.ru_stime); @@ -1304,7 +1304,7 @@ loop: p->p_flag |= P_WAITED; sx_sunlock(&proctree_lock); pid = p->p_pid; - status = W_STOPCODE(p->p_xstat); + status = W_STOPCODE(p->p_xsig); ru = p->p_ru; PROC_STATLOCK(p); calcru(p, &ru.ru_utime, &ru.ru_stime); Modified: head/sys/fs/procfs/procfs_ctl.c ============================================================================== --- head/sys/fs/procfs/procfs_ctl.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/fs/procfs/procfs_ctl.c Sat Jul 18 09:02:50 2015 (r285670) @@ -142,7 +142,7 @@ procfs_control(struct thread *td, struct */ p->p_flag |= P_TRACED; faultin(p); - p->p_xstat = 0; /* XXX ? */ + p->p_xsig = 0; /* XXX ? */ p->p_oppid = p->p_pptr->p_pid; if (p->p_pptr != td->td_proc) { proc_reparent(p, td->td_proc); @@ -198,7 +198,7 @@ out: * To continue with a signal, just send * the signal name to the ctl file */ - p->p_xstat = 0; + p->p_xsig = 0; switch (op) { /* @@ -340,7 +340,7 @@ procfs_doprocctl(PFS_FILL_ARGS) PROC_LOCK(p); if (TRACE_WAIT_P(td->td_proc, p)) { - p->p_xstat = nm->nm_val; + p->p_xsig = nm->nm_val; #ifdef FIX_SSTEP FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); #endif Modified: head/sys/fs/procfs/procfs_ioctl.c ============================================================================== --- head/sys/fs/procfs/procfs_ioctl.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/fs/procfs/procfs_ioctl.c Sat Jul 18 09:02:50 2015 (r285670) @@ -140,7 +140,7 @@ procfs_ioctl(PFS_IOCTL_ARGS) ps->flags = 0; /* nope */ ps->events = p->p_stops; ps->why = p->p_step ? p->p_stype : 0; - ps->val = p->p_step ? p->p_xstat : 0; + ps->val = p->p_step ? p->p_xsig : 0; break; #ifdef COMPAT_FREEBSD32 case PIOCWAIT32: @@ -160,7 +160,7 @@ procfs_ioctl(PFS_IOCTL_ARGS) ps32->flags = 0; /* nope */ ps32->events = p->p_stops; ps32->why = p->p_step ? p->p_stype : 0; - ps32->val = p->p_step ? p->p_xstat : 0; + ps32->val = p->p_step ? p->p_xsig : 0; break; #endif #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) @@ -182,7 +182,7 @@ procfs_ioctl(PFS_IOCTL_ARGS) #if 0 p->p_step = 0; if (P_SHOULDSTOP(p)) { - p->p_xstat = sig; + p->p_xsig = sig; p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG); PROC_SLOCK(p); thread_unsuspend(p); Modified: head/sys/kern/kern_event.c ============================================================================== --- head/sys/kern/kern_event.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_event.c Sat Jul 18 09:02:50 2015 (r285670) @@ -436,7 +436,7 @@ filt_proc(struct knote *kn, long hint) kn->kn_flags |= EV_EOF | EV_ONESHOT; kn->kn_ptr.p_proc = NULL; if (kn->kn_fflags & NOTE_EXIT) - kn->kn_data = p->p_xstat; + kn->kn_data = KW_EXITCODE(p->p_xexit, p->p_xsig); if (kn->kn_fflags == 0) kn->kn_flags |= EV_DROP; return (1); Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_exec.c Sat Jul 18 09:02:50 2015 (r285670) @@ -920,7 +920,7 @@ done2: if (error && imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ - exit1(td, W_EXITCODE(0, SIGABRT)); + exit1(td, 0, SIGABRT); /* NOT REACHED */ } Modified: head/sys/kern/kern_exit.c ============================================================================== --- head/sys/kern/kern_exit.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_exit.c Sat Jul 18 09:02:50 2015 (r285670) @@ -175,7 +175,7 @@ void sys_sys_exit(struct thread *td, struct sys_exit_args *uap) { - exit1(td, W_EXITCODE(uap->rval, 0)); + exit1(td, uap->rval, 0); /* NOTREACHED */ } @@ -185,13 +185,14 @@ sys_sys_exit(struct thread *td, struct s * and rusage for wait(). Check for child processes and orphan them. */ void -exit1(struct thread *td, int rv) +exit1(struct thread *td, int rval, int signo) { struct proc *p, *nq, *q, *t; struct thread *tdt; struct vnode *ttyvp = NULL; mtx_assert(&Giant, MA_NOTOWNED); + KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo)); p = td->td_proc; /* @@ -200,8 +201,7 @@ exit1(struct thread *td, int rv) * shutdown on sparc64 when the gmirror worker process exists. */ if (p == initproc && rebooting == 0) { - printf("init died (signal %d, exit %d)\n", - WTERMSIG(rv), WEXITSTATUS(rv)); + printf("init died (signal %d, exit %d)\n", signo, rval); panic("Going nowhere without my init!"); } @@ -257,6 +257,11 @@ exit1(struct thread *td, int rv) KASSERT(p->p_numthreads == 1, ("exit1: proc %p exiting with %d threads", p, p->p_numthreads)); racct_sub(p, RACCT_NTHR, 1); + + /* Let event handler change exit status */ + p->p_xexit = rval; + p->p_xsig = signo; + /* * Wakeup anyone in procfs' PIOCWAIT. They should have a hold * on our vmspace, so we should block below until they have @@ -264,7 +269,7 @@ exit1(struct thread *td, int rv) * requested S_EXIT stops we will block here until they ack * via PIOCCONT. */ - _STOPEVENT(p, S_EXIT, rv); + _STOPEVENT(p, S_EXIT, 0); /* * Ignore any pending request to stop due to a stop signal. @@ -289,7 +294,6 @@ exit1(struct thread *td, int rv) while (p->p_lock > 0) msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0); - p->p_xstat = rv; /* Let event handler change exit status */ PROC_UNLOCK(p); /* Drain the limit callout while we don't have the proc locked */ callout_drain(&p->p_limco); @@ -301,7 +305,7 @@ exit1(struct thread *td, int rv) * it was. The exit status is WEXITSTATUS(rv), but it's not clear * what the return value is. */ - AUDIT_ARG_EXIT(WEXITSTATUS(rv), 0); + AUDIT_ARG_EXIT(rval, 0); AUDIT_SYSCALL_EXIT(0, td); #endif @@ -322,7 +326,8 @@ exit1(struct thread *td, int rv) /* * Check if any loadable modules need anything done at process exit. - * E.g. SYSV IPC stuff + * E.g. SYSV IPC stuff. + * Event handler could change exit status. * XXX what if one of these generates an error? */ EVENTHANDLER_INVOKE(process_exit, p); @@ -332,7 +337,6 @@ exit1(struct thread *td, int rv) * P_PPWAIT is set; we will wakeup the parent below. */ PROC_LOCK(p); - rv = p->p_xstat; /* Event handler could change exit status */ stopprofclock(p); p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE); @@ -561,9 +565,9 @@ exit1(struct thread *td, int rv) #ifdef KDTRACE_HOOKS int reason = CLD_EXITED; - if (WCOREDUMP(rv)) + if (WCOREDUMP(signo)) reason = CLD_DUMPED; - else if (WIFSIGNALED(rv)) + else if (WIFSIGNALED(signo)) reason = CLD_KILLED; SDT_PROBE(proc, kernel, , exit, reason, 0, 0, 0, 0); #endif @@ -742,7 +746,7 @@ out: sbuf_finish(sb); log(LOG_INFO, "%s", sbuf_data(sb)); sbuf_delete(sb); - exit1(td, W_EXITCODE(0, sig)); + exit1(td, 0, sig); return (0); } @@ -841,7 +845,7 @@ proc_reap(struct thread *td, struct proc PROC_SUNLOCK(p); if (status) - *status = p->p_xstat; /* convert to int */ + *status = KW_EXITCODE(p->p_xexit, p->p_xsig); if (options & WNOWAIT) { /* * Only poll, returning the status. Caller does not wish to @@ -905,7 +909,7 @@ proc_reap(struct thread *td, struct proc * nothing can reach this process anymore. As such further locking * is unnecessary. */ - p->p_xstat = 0; /* XXX: why? */ + p->p_xexit = p->p_xsig = 0; /* XXX: why? */ PROC_LOCK(q); ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, &p->p_rux); @@ -1064,15 +1068,15 @@ proc_to_reap(struct thread *td, struct p * This is still a rough estimate. We will fix the * cases TRAPPED, STOPPED, and CONTINUED later. */ - if (WCOREDUMP(p->p_xstat)) { + if (WCOREDUMP(p->p_xsig)) { siginfo->si_code = CLD_DUMPED; - siginfo->si_status = WTERMSIG(p->p_xstat); - } else if (WIFSIGNALED(p->p_xstat)) { + siginfo->si_status = WTERMSIG(p->p_xsig); + } else if (WIFSIGNALED(p->p_xsig)) { siginfo->si_code = CLD_KILLED; - siginfo->si_status = WTERMSIG(p->p_xstat); + siginfo->si_status = WTERMSIG(p->p_xsig); } else { siginfo->si_code = CLD_EXITED; - siginfo->si_status = WEXITSTATUS(p->p_xstat); + siginfo->si_status = p->p_xexit; } siginfo->si_pid = p->p_pid; @@ -1223,9 +1227,9 @@ loop: sx_xunlock(&proctree_lock); if (status != NULL) - *status = W_STOPCODE(p->p_xstat); + *status = W_STOPCODE(p->p_xsig); if (siginfo != NULL) { - siginfo->si_status = p->p_xstat; + siginfo->si_status = p->p_xsig; siginfo->si_code = CLD_TRAPPED; } if ((options & WNOWAIT) == 0) { @@ -1236,7 +1240,7 @@ loop: CTR4(KTR_PTRACE, "wait: returning trapped pid %d status %#x (xstat %d) xthread %d", - p->p_pid, W_STOPCODE(p->p_xstat), p->p_xstat, + p->p_pid, W_STOPCODE(p->p_xsig), p->p_xsig, p->p_xthread != NULL ? p->p_xthread->td_tid : -1); PROC_UNLOCK(p); td->td_retval[0] = pid; @@ -1252,9 +1256,9 @@ loop: sx_xunlock(&proctree_lock); if (status != NULL) - *status = W_STOPCODE(p->p_xstat); + *status = W_STOPCODE(p->p_xsig); if (siginfo != NULL) { - siginfo->si_status = p->p_xstat; + siginfo->si_status = p->p_xsig; siginfo->si_code = CLD_STOPPED; } if ((options & WNOWAIT) == 0) { Modified: head/sys/kern/kern_kthread.c ============================================================================== --- head/sys/kern/kern_kthread.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_kthread.c Sat Jul 18 09:02:50 2015 (r285670) @@ -162,7 +162,7 @@ kproc_exit(int ecode) wakeup(p); /* Buh-bye! */ - exit1(td, W_EXITCODE(ecode, 0)); + exit1(td, ecode, 0); } /* Modified: head/sys/kern/kern_proc.c ============================================================================== --- head/sys/kern/kern_proc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_proc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -41,7 +41,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -68,9 +70,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include -#include +#include #ifdef DDB #include @@ -920,7 +921,7 @@ fill_kinfo_proc_only(struct proc *p, str p->p_sysent->sv_name[0] != '\0') strlcpy(kp->ki_emul, p->p_sysent->sv_name, sizeof(kp->ki_emul)); kp->ki_siglist = p->p_siglist; - kp->ki_xstat = p->p_xstat; + kp->ki_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig); kp->ki_acflag = p->p_acflag; kp->ki_lock = p->p_lock; if (p->p_pptr) { Modified: head/sys/kern/kern_sig.c ============================================================================== --- head/sys/kern/kern_sig.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/kern_sig.c Sat Jul 18 09:02:50 2015 (r285670) @@ -2227,7 +2227,7 @@ tdsendsignal(struct proc *p, struct thre if (p->p_numthreads == p->p_suspcount) { PROC_SUNLOCK(p); p->p_flag |= P_CONTINUED; - p->p_xstat = SIGCONT; + p->p_xsig = SIGCONT; PROC_LOCK(p->p_pptr); childproc_continued(p); PROC_UNLOCK(p->p_pptr); @@ -2306,7 +2306,7 @@ tdsendsignal(struct proc *p, struct thre if (p->p_flag & (P_PPWAIT|P_WEXIT)) goto out; p->p_flag |= P_STOPPED_SIG; - p->p_xstat = sig; + p->p_xsig = sig; PROC_SLOCK(p); sig_suspend_threads(td, p, 1); if (p->p_numthreads == p->p_suspcount) { @@ -2319,7 +2319,7 @@ tdsendsignal(struct proc *p, struct thre */ thread_stopped(p); PROC_SUNLOCK(p); - sigqueue_delete_proc(p, p->p_xstat); + sigqueue_delete_proc(p, p->p_xsig); } else PROC_SUNLOCK(p); goto out; @@ -2491,7 +2491,7 @@ ptracestop(struct thread *td, int sig) * Just make wait() to work, the last stopped thread * will win. */ - p->p_xstat = sig; + p->p_xsig = sig; p->p_xthread = td; p->p_flag |= (P_STOPPED_SIG|P_STOPPED_TRACE); sig_suspend_threads(td, p, 0); @@ -2684,7 +2684,7 @@ issignal(struct thread *td) /* * If parent wants us to take the signal, - * then it will leave it in p->p_xstat; + * then it will leave it in p->p_xsig; * otherwise we just look for signals again. */ if (newsig == 0) @@ -2761,7 +2761,7 @@ issignal(struct thread *td) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.lock_object, "Catching SIGSTOP"); p->p_flag |= P_STOPPED_SIG; - p->p_xstat = sig; + p->p_xsig = sig; PROC_SLOCK(p); sig_suspend_threads(td, p, 0); thread_suspend_switch(td, p); @@ -2965,7 +2965,7 @@ sigexit(td, sig) sig & WCOREFLAG ? " (core dumped)" : ""); } else PROC_UNLOCK(p); - exit1(td, W_EXITCODE(0, sig)); + exit1(td, 0, sig); /* NOTREACHED */ } @@ -3020,8 +3020,8 @@ childproc_jobstate(struct proc *p, int r void childproc_stopped(struct proc *p, int reason) { - /* p_xstat is a plain signal number, not a full wait() status here. */ - childproc_jobstate(p, reason, p->p_xstat); + + childproc_jobstate(p, reason, p->p_xsig); } void @@ -3033,16 +3033,18 @@ childproc_continued(struct proc *p) void childproc_exited(struct proc *p) { - int reason; - int xstat = p->p_xstat; /* convert to int */ - int status; - - if (WCOREDUMP(xstat)) - reason = CLD_DUMPED, status = WTERMSIG(xstat); - else if (WIFSIGNALED(xstat)) - reason = CLD_KILLED, status = WTERMSIG(xstat); - else - reason = CLD_EXITED, status = WEXITSTATUS(xstat); + int reason, status; + + if (WCOREDUMP(p->p_xsig)) { + reason = CLD_DUMPED; + status = WTERMSIG(p->p_xsig); + } else if (WIFSIGNALED(p->p_xsig)) { + reason = CLD_KILLED; + status = WTERMSIG(p->p_xsig); + } else { + reason = CLD_EXITED; + status = p->p_xexit; + } /* * XXX avoid calling wakeup(p->p_pptr), the work is * done in exit1(). Modified: head/sys/kern/sys_procdesc.c ============================================================================== --- head/sys/kern/sys_procdesc.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/sys_procdesc.c Sat Jul 18 09:02:50 2015 (r285670) @@ -295,7 +295,7 @@ procdesc_exit(struct proc *p) ("procdesc_exit: closed && parent not init")); pd->pd_flags |= PDF_EXITED; - pd->pd_xstat = p->p_xstat; + pd->pd_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig); /* * If the process descriptor has been closed, then we have nothing Modified: head/sys/kern/sys_process.c ============================================================================== --- head/sys/kern/sys_process.c Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/kern/sys_process.c Sat Jul 18 09:02:50 2015 (r285670) @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -975,7 +976,7 @@ kern_ptrace(struct thread *td, int req, sx_xunlock(&proctree_lock); proctree_locked = 0; } - p->p_xstat = data; + p->p_xsig = data; p->p_xthread = NULL; if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) { /* deliver or queue signal */ @@ -1300,7 +1301,8 @@ stopevent(struct proc *p, unsigned int e CTR3(KTR_PTRACE, "stopevent: pid %d event %u val %u", p->p_pid, event, val); do { - p->p_xstat = val; + if (event != S_EXIT) + p->p_xsig = val; p->p_xthread = NULL; p->p_stype = event; /* Which event caused the stop? */ wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */ Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/sys/proc.h Sat Jul 18 09:02:50 2015 (r285670) @@ -585,10 +585,10 @@ struct proc { pid_t p_reapsubtree; /* (e) Pid of the direct child of the reaper which spawned our subtree. */ + u_int p_xexit; /* (c) Exit code. */ + u_int p_xsig; /* (c) Stop/kill sig. */ /* End area that is copied on creation. */ -#define p_endcopy p_xstat - - u_short p_xstat; /* (c) Exit status; also stop sig. */ +#define p_endcopy p_xsig struct knlist p_klist; /* (c) Knotes attached to this proc. */ int p_numthreads; /* (c) Number of threads. */ struct mdproc p_md; /* Any machine-dependent fields. */ @@ -970,7 +970,7 @@ void unsleep(struct thread *); void userret(struct thread *, struct trapframe *); void cpu_exit(struct thread *); -void exit1(struct thread *, int) __dead2; +void exit1(struct thread *, int, int) __dead2; struct syscall_args; int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa); void cpu_fork(struct thread *, struct proc *, struct thread *, int); Modified: head/sys/sys/wait.h ============================================================================== --- head/sys/sys/wait.h Sat Jul 18 06:48:30 2015 (r285669) +++ head/sys/sys/wait.h Sat Jul 18 09:02:50 2015 (r285670) @@ -138,7 +138,19 @@ typedef enum #define WAIT_MYPGRP 0 /* any process in my process group */ #endif /* __BSD_VISIBLE */ +#if defined(_KERNEL) || defined(_WANT_KW_EXITCODE) + +/* + * Clamp the return code to the low 8 bits from full 32 bit value. + * Should be used in kernel to construct the wait(2)-compatible process + * status to usermode. + */ +#define KW_EXITCODE(ret, sig) W_EXITCODE((ret) & 0xff, (sig)) + +#endif /* _KERNEL || _WANT_KW_EXITCODE */ + #ifndef _KERNEL + #include __BEGIN_DECLS