mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-28 11:57:28 +00:00
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
This commit is contained in:
parent
ddee45244d
commit
b4490c6e93
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285670
@ -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
|
||||
|
@ -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 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
|
||||
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) {
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ linux_exit(struct thread *td, struct linux_exit_args *args)
|
||||
* 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 */
|
||||
}
|
||||
|
||||
|
@ -1839,7 +1839,7 @@ linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
|
||||
* 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 */
|
||||
}
|
||||
|
||||
|
@ -1277,7 +1277,7 @@ svr4_sys_waitsys(td, uap)
|
||||
|
||||
/* 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 @@ svr4_sys_waitsys(td, uap)
|
||||
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);
|
||||
|
@ -142,7 +142,7 @@ procfs_control(struct thread *td, struct proc *p, int op)
|
||||
*/
|
||||
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 @@ procfs_control(struct thread *td, struct proc *p, int op)
|
||||
* 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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -920,7 +920,7 @@ do_execve(td, args, mac_p)
|
||||
|
||||
if (error && imgp->vmspace_destroyed) {
|
||||
/* sorry, no more process anymore. exit gracefully */
|
||||
exit1(td, W_EXITCODE(0, SIGABRT));
|
||||
exit1(td, 0, SIGABRT);
|
||||
/* NOT REACHED */
|
||||
}
|
||||
|
||||
|
@ -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 @@ sys_abort2(struct thread *td, struct abort2_args *uap)
|
||||
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 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
|
||||
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 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
|
||||
|
||||
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 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
|
||||
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) {
|
||||
|
@ -162,7 +162,7 @@ kproc_exit(int ecode)
|
||||
wakeup(p);
|
||||
|
||||
/* Buh-bye! */
|
||||
exit1(td, W_EXITCODE(ecode, 0));
|
||||
exit1(td, ecode, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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, struct kinfo_proc *kp)
|
||||
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) {
|
||||
|
@ -2227,7 +2227,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
|
||||
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 thread *td, int sig, ksiginfo_t *ksi)
|
||||
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 thread *td, int sig, ksiginfo_t *ksi)
|
||||
*/
|
||||
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 reason, int sig)
|
||||
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;
|
||||
int reason, 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);
|
||||
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().
|
||||
|
@ -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
|
||||
|
@ -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, pid_t pid, void *addr, int data)
|
||||
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 event, unsigned int val)
|
||||
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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user