summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exit.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-07-18 09:02:50 +0000
committerkib <kib@FreeBSD.org>2015-07-18 09:02:50 +0000
commit48ccbdea817fb25a05eb4024844eec6ec81249a7 (patch)
tree5d1411f5124df7d1ff8fb76e514e51a232fa0406 /sys/kern/kern_exit.c
parentcad9ad69e50ec0e79836106ef79f5c6e37973b3d (diff)
downloadFreeBSD-src-48ccbdea817fb25a05eb4024844eec6ec81249a7.zip
FreeBSD-src-48ccbdea817fb25a05eb4024844eec6ec81249a7.tar.gz
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
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r--sys/kern/kern_exit.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 8fe968e..3310d1d 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -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 sys_exit_args *uap)
* 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 *p, int *status, int options)
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 *p, int *status, int options)
* 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 proc *p, idtype_t idtype, id_t id,
* 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) {
OpenPOWER on IntegriCloud