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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to