Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Jul 2015 09:02:51 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
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
Message-ID:  <201507180902.t6I92pg2079712@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/tty.h>
 #include <sys/file.h>
 #include <sys/conf.h>
+#define	_WANT_KW_EXITCODE
+#include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -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 <sys/param.h>
 #include <sys/systm.h>
 #include <sys/elf.h>
+#include <sys/eventhandler.h>
 #include <sys/exec.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
@@ -68,9 +70,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sdt.h>
 #include <sys/sx.h>
 #include <sys/user.h>
-#include <sys/jail.h>
 #include <sys/vnode.h>
-#include <sys/eventhandler.h>
+#include <sys/wait.h>
 
 #ifdef DDB
 #include <ddb/ddb.h>
@@ -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 <sys/syscallsubr.h>
 #include <sys/sysent.h>
 #include <sys/sysproto.h>
+#include <sys/pioctl.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
@@ -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 <sys/types.h>
 
 __BEGIN_DECLS



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507180902.t6I92pg2079712>