X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/7b1edb791d9ca667b95988cb5638c4c88416cd17..cf03f5cdc65293b4cb5eba3ed23fed26dad903c9:/bsd/kern/kern_exit.c?ds=sidebyside diff --git a/bsd/kern/kern_exit.c b/bsd/kern/kern_exit.c index 84c51a09c..25dc9ef71 100644 --- a/bsd/kern/kern_exit.c +++ b/bsd/kern/kern_exit.c @@ -1,21 +1,24 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -86,7 +89,11 @@ #include #include #include +#include #include +#if KTRACE +#include +#endif extern char init_task_failure_data[]; int exit1 __P((struct proc *, int, int *)); @@ -106,12 +113,12 @@ exit(p, uap, retval) { exit1(p, W_EXITCODE(uap->rval, 0), retval); - /* drop funnel befewo we return */ + /* drop funnel before we return */ thread_funnel_set(kernel_flock, FALSE); thread_exception_return(); /* NOTREACHED */ while (TRUE) - thread_block(0); + thread_block(THREAD_CONTINUE_NULL); /* NOTREACHED */ } @@ -141,7 +148,7 @@ exit1(p, rv, retval) ut = get_bsdthread_info(th_act_self); if (ut->uu_flag & P_VFORK) { - vfork_exit(p, rv); + (void)vfork_exit(p, rv); vfork_return(th_act_self, p->p_pptr, p , retval); unix_syscall_return(0); /* NOT REACHED */ @@ -172,7 +179,7 @@ exit1(p, rv, retval) s = splsched(); p->p_flag |= P_WEXIT; splx(s); - proc_prepareexit(p); + (void)proc_prepareexit(p); p->p_xstat = rv; /* task terminate will call proc_terminate and that cleans it up */ @@ -224,14 +231,14 @@ proc_prepareexit(struct proc *p) p->p_sigignore = ~0; p->p_siglist = 0; ut = get_bsdthread_info(th_act_self); - ut->uu_sig = 0; - untimeout(realitexpire, (caddr_t)p); + ut->uu_siglist = 0; + untimeout(realitexpire, (caddr_t)p->p_pid); } void proc_exit(struct proc *p) { - register struct proc *q, *nq; + register struct proc *q, *nq, *pp; thread_t self = current_thread(); thread_act_t th_act_self = current_act(); struct task *task = p->task; @@ -262,11 +269,15 @@ proc_exit(struct proc *p) /* Close ref SYSV Shared memory*/ if (p->vm_shm) shmexit(p); + /* Release SYSV semaphores */ + semexit(p); if (SESS_LEADER(p)) { register struct session *sp = p->p_session; if (sp->s_ttyvp) { + struct vnode *ttyvp; + /* * Controlling process. * Signal foreground pgrp, @@ -284,9 +295,10 @@ proc_exit(struct proc *p) if (sp->s_ttyvp) VOP_REVOKE(sp->s_ttyvp, REVOKEALL); } - if (sp->s_ttyvp) - vrele(sp->s_ttyvp); + ttyvp = sp->s_ttyvp; sp->s_ttyvp = NULL; + if (ttyvp) + vrele(ttyvp); /* * s_ttyp is not zero'd; we use this to indicate * that the session once had a controlling terminal. @@ -298,16 +310,20 @@ proc_exit(struct proc *p) fixjobc(p, p->p_pgrp, 0); p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; + (void)acct_process(p); + #if KTRACE /* * release trace file */ p->p_traceflag = 0; /* don't trace the vrele() */ - if (p->p_tracep) - vrele(p->p_tracep); + if (p->p_tracep) { + struct vnode *tvp = p->p_tracep; + p->p_tracep = NULL; + vrele(tvp); + } #endif - q = p->p_children.lh_first; if (q) /* only need this if any child is S_ZOMB */ wakeup((caddr_t) initproc); @@ -321,7 +337,9 @@ proc_exit(struct proc *p) if (q->p_flag & P_TRACED) { q->p_flag &= ~P_TRACED; if (q->sigwait_thread) { - thread_t sig_shuttle = getshuttle_thread(q->sigwait_thread); + thread_t sig_shuttle; + + sig_shuttle = (thread_t)getshuttle_thread((thread_act_t)q->sigwait_thread); /* * The sigwait_thread could be stopped at a * breakpoint. Wake it up to kill. @@ -329,9 +347,9 @@ proc_exit(struct proc *p) * the first thread in the task. So any attempts to kill * the process would result into a deadlock on q->sigwait. */ - thread_resume((struct thread *)q->sigwait_thread); + thread_resume((thread_act_t)q->sigwait_thread); clear_wait(sig_shuttle, THREAD_INTERRUPTED); - threadsignal(q->sigwait_thread, SIGKILL, 0); + threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0); } psignal(q, SIGKILL); } @@ -415,7 +433,24 @@ proc_exit(struct proc *p) /* * Notify parent that we're gone. */ - psignal(p->p_pptr, SIGCHLD); + if (p->p_pptr->p_flag & P_NOCLDWAIT) { + struct proc * pp = p->p_pptr; + + proc_reparent(p, initproc); + /* If there are no more children wakeup parent */ + if (LIST_EMPTY(&pp->p_children)) + wakeup((caddr_t)pp); + } + /* should be fine as parent proc would be initproc */ + pp = p->p_pptr; + if (pp != initproc) { + pp->si_pid = p->p_pid; + pp->si_status = p->p_xstat; + pp->si_code = CLD_EXITED; + pp->si_uid = p->p_cred->p_ruid; + } + psignal(pp, SIGCHLD); + /* Place onto zombproc. */ LIST_INSERT_HEAD(&zombproc, p, p_list); @@ -503,8 +538,8 @@ wait1continue(result) p = current_proc(); thread = current_act(); - vt = get_bsduthreadarg(thread); - retval = get_bsduthreadrval(thread); + vt = (void *)get_bsduthreadarg(thread); + retval = (int *)get_bsduthreadrval(thread); wait1((struct proc *)p, (struct wait4_args *)vt, retval, 0); } @@ -520,6 +555,7 @@ wait1(q, uap, retval, compat) register int nfound; register struct proc *p, *t; int status, error; + struct vnode *tvp; retry: if (uap->pid == 0) @@ -571,6 +607,12 @@ loop: if (p->p_oppid && (t = pfind(p->p_oppid))) { p->p_oppid = 0; proc_reparent(p, t); + if (t != initproc) { + t->si_pid = p->p_pid; + t->si_status = p->p_xstat; + t->si_code = CLD_CONTINUED; + t->si_uid = p->p_cred->p_ruid; + } psignal(t, SIGCHLD); wakeup((caddr_t)t); p->p_flag &= ~P_WAITING; @@ -610,8 +652,10 @@ loop: /* * Release reference to text vnode */ - if (p->p_textvp) - vrele(p->p_textvp); + tvp = p->p_textvp; + p->p_textvp = NULL; + if (tvp) + vrele(tvp); /* * Finally finished with old proc entry. @@ -729,7 +773,7 @@ process_terminate_self(void) void vfork_exit(p, rv) - register struct proc *p; + struct proc *p; int rv; { register struct proc *q, *nq; @@ -789,18 +833,18 @@ panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data); p->p_sigignore = ~0; p->p_siglist = 0; - ut->uu_sig = 0; - untimeout(realitexpire, (caddr_t)p); + ut->uu_siglist = 0; + untimeout(realitexpire, (caddr_t)p->p_pid); p->p_xstat = rv; - vproc_exit(p); + (void)vproc_exit(p); } void vproc_exit(struct proc *p) { - register struct proc *q, *nq; + register struct proc *q, *nq, *pp; thread_t self = current_thread(); thread_act_t th_act_self = current_act(); struct task *task = p->task; @@ -816,14 +860,12 @@ vproc_exit(struct proc *p) */ fdfree(p); - /* Close ref SYSV Shared memory*/ - if (p->vm_shm) - shmexit(p); - if (SESS_LEADER(p)) { register struct session *sp = p->p_session; if (sp->s_ttyvp) { + struct vnode *ttyvp; + /* * Controlling process. * Signal foreground pgrp, @@ -841,9 +883,10 @@ vproc_exit(struct proc *p) if (sp->s_ttyvp) VOP_REVOKE(sp->s_ttyvp, REVOKEALL); } - if (sp->s_ttyvp) - vrele(sp->s_ttyvp); + ttyvp = sp->s_ttyvp; sp->s_ttyvp = NULL; + if (ttyvp) + vrele(ttyvp); /* * s_ttyp is not zero'd; we use this to indicate * that the session once had a controlling terminal. @@ -855,13 +898,17 @@ vproc_exit(struct proc *p) fixjobc(p, p->p_pgrp, 0); p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; + #if KTRACE /* * release trace file */ p->p_traceflag = 0; /* don't trace the vrele() */ - if (p->p_tracep) - vrele(p->p_tracep); + if (p->p_tracep) { + struct vnode *tvp = p->p_tracep; + p->p_tracep = NULL; + vrele(tvp); + } #endif q = p->p_children.lh_first; @@ -877,7 +924,9 @@ vproc_exit(struct proc *p) if (q->p_flag & P_TRACED) { q->p_flag &= ~P_TRACED; if (q->sigwait_thread) { - thread_t sig_shuttle = getshuttle_thread(q->sigwait_thread); + thread_t sig_shuttle; + + sig_shuttle = (thread_t) getshuttle_thread((thread_act_t)q->sigwait_thread); /* * The sigwait_thread could be stopped at a * breakpoint. Wake it up to kill. @@ -885,9 +934,9 @@ vproc_exit(struct proc *p) * the first thread in the task. So any attempts to kill * the process would result into a deadlock on q->sigwait. */ - thread_resume((struct thread *)q->sigwait_thread); + thread_resume((thread_act_t)q->sigwait_thread); clear_wait(sig_shuttle, THREAD_INTERRUPTED); - threadsignal(q->sigwait_thread, SIGKILL, 0); + threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0); } psignal(q, SIGKILL); } @@ -971,6 +1020,13 @@ vproc_exit(struct proc *p) /* * Notify parent that we're gone. */ + pp = p->p_pptr; + if (pp != initproc) { + pp->si_pid = p->p_pid; + pp->si_status = p->p_xstat; + pp->si_code = CLD_EXITED; + pp->si_uid = p->p_cred->p_ruid; + } psignal(p->p_pptr, SIGCHLD); /* Place onto zombproc. */