]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_exit.c
xnu-517.9.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_exit.c
index 84c51a09c7dbb7db0435ce8c41eda14f8ebdf9a5..157ec5f05ce9a51c2f90ce9b69010607fc4184dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <sys/resourcevar.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
 #include <sys/resourcevar.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
+#include <sys/aio_kern.h>
+
+#include <bsm/audit_kernel.h>
+#include <bsm/audit_kevents.h>
 
 #include <mach/mach_types.h>
 #include <kern/thread.h>
 #include <kern/thread_act.h>
 
 #include <mach/mach_types.h>
 #include <kern/thread.h>
 #include <kern/thread_act.h>
+#include <kern/sched_prim.h>
 #include <kern/assert.h>
 #include <kern/assert.h>
+#if KTRACE   
+#include <sys/ktrace.h>
+#include <sys/ubc.h>
+#endif
 
 extern char init_task_failure_data[];
 int exit1 __P((struct proc *, int, int *));
 
 extern char init_task_failure_data[];
 int exit1 __P((struct proc *, int, int *));
+void proc_prepareexit(struct proc *p);
+int vfork_exit(struct proc *p, int rv);
+void vproc_exit(struct proc *p);
 
 /*
  * exit --
 
 /*
  * exit --
@@ -106,12 +118,12 @@ exit(p, uap, retval)
 {
        exit1(p, W_EXITCODE(uap->rval, 0), 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_funnel_set(kernel_flock, FALSE);
        thread_exception_return();
        /* NOTREACHED */
        while (TRUE)
-               thread_block(0);
+               thread_block(THREAD_CONTINUE_NULL);
        /* NOTREACHED */
 }
 
        /* NOTREACHED */
 }
 
@@ -127,8 +139,7 @@ exit1(p, rv, retval)
        int * retval;
 {
        register struct proc *q, *nq;
        int * retval;
 {
        register struct proc *q, *nq;
-       thread_t self = current_thread();
-       thread_act_t th_act_self = current_act();
+       thread_act_t self = current_act();
        struct task *task = p->task;
        register int i,s;
        struct uthread *ut;
        struct task *task = p->task;
        register int i,s;
        struct uthread *ut;
@@ -139,22 +150,25 @@ exit1(p, rv, retval)
         * right here.
         */
 
         * right here.
         */
 
-        ut = get_bsdthread_info(th_act_self);
+        ut = get_bsdthread_info(self);
         if (ut->uu_flag & P_VFORK) {
         if (ut->uu_flag & P_VFORK) {
-                       vfork_exit(p, rv);
-                       vfork_return(th_act_self, p->p_pptr, p , retval);
+               if (!vfork_exit(p, rv)) {
+                       vfork_return(self, p->p_pptr, p , retval);
                        unix_syscall_return(0);
                        /* NOT REACHED */
                        unix_syscall_return(0);
                        /* NOT REACHED */
+               }  
+               return(EINVAL);
         }
         }
+       AUDIT_SYSCALL_EXIT(0, p, ut); /* Exit is always successfull */
         signal_lock(p);
        while (p->exit_thread != self) {
                if (sig_try_locked(p) <= 0) {
         signal_lock(p);
        while (p->exit_thread != self) {
                if (sig_try_locked(p) <= 0) {
-                       if (get_threadtask(th_act_self) != task) {
+                       if (get_threadtask(self) != task) {
                                 signal_unlock(p);
                                return(0);
                         }
                        signal_unlock(p);
                                 signal_unlock(p);
                                return(0);
                         }
                        signal_unlock(p);
-                       thread_terminate(th_act_self);
+                       thread_terminate(self);
                        thread_funnel_set(kernel_flock, FALSE);
                        thread_exception_return();
                        /* NOTREACHED */
                        thread_funnel_set(kernel_flock, FALSE);
                        thread_exception_return();
                        /* NOTREACHED */
@@ -178,21 +192,6 @@ exit1(p, rv, retval)
        /* task terminate will call proc_terminate and that cleans it up */
        task_terminate_internal(task);
 
        /* task terminate will call proc_terminate and that cleans it up */
        task_terminate_internal(task);
 
-       /*
-        * we come back and returns to AST which 
-        * should cleanup the rest 
-        */
-#if 0
-       if (task == current_task()) {
-               thread_exception_return();
-               /*NOTREACHED*/
-       }
-
-       while (task == current_task()) {
-               thread_terminate_self();
-               /*NOTREACHED*/
-       }
-#endif
        return(0);
 }
 
        return(0);
 }
 
@@ -201,8 +200,12 @@ proc_prepareexit(struct proc *p)
 {
        int s;
        struct uthread *ut;
 {
        int s;
        struct uthread *ut;
-       thread_t self = current_thread();
-       thread_act_t th_act_self = current_act();
+       exception_data_t        code[EXCEPTION_CODE_MAX];
+       thread_act_t self = current_act();
+
+       code[0] = 0xFF000001;                   /* Set terminate code */
+       code[1] = p->p_pid;                             /* Pass out the pid     */
+       (void)sys_perf_notify(p->task, &code, 2);       /* Notify the perf server */
 
        /*
         * Remove proc from allproc queue and from pidhash chain.
 
        /*
         * Remove proc from allproc queue and from pidhash chain.
@@ -211,6 +214,7 @@ proc_prepareexit(struct proc *p)
         * in partially cleaned state.
         */
        LIST_REMOVE(p, p_list);
         * in partially cleaned state.
         */
        LIST_REMOVE(p, p_list);
+       LIST_INSERT_HEAD(&zombproc, p, p_list); /* Place onto zombproc. */
        LIST_REMOVE(p, p_hash);
 
 #ifdef PGINPROF
        LIST_REMOVE(p, p_hash);
 
 #ifdef PGINPROF
@@ -223,17 +227,15 @@ proc_prepareexit(struct proc *p)
        p->p_flag &= ~(P_TRACED | P_PPWAIT);
        p->p_sigignore = ~0;
        p->p_siglist = 0;
        p->p_flag &= ~(P_TRACED | P_PPWAIT);
        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 = get_bsdthread_info(self);
+       ut->uu_siglist = 0;
+       untimeout(realitexpire, (caddr_t)p->p_pid);
 }
 
 void 
 proc_exit(struct proc *p)
 {
 }
 
 void 
 proc_exit(struct proc *p)
 {
-       register struct proc *q, *nq;
-       thread_t self = current_thread();
-       thread_act_t th_act_self = current_act();
+       register struct proc *q, *nq, *pp;
        struct task *task = p->task;
        register int i,s;
        boolean_t funnel_state;
        struct task *task = p->task;
        register int i,s;
        boolean_t funnel_state;
@@ -253,6 +255,12 @@ proc_exit(struct proc *p)
        MALLOC_ZONE(p->p_ru, struct rusage *,
                        sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
 
        MALLOC_ZONE(p->p_ru, struct rusage *,
                        sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
 
+       /*
+        * need to cancel async IO requests that can be cancelled and wait for those
+        * already active.  MAY BLOCK!
+        */
+       _aio_exit( p );
+
        /*
         * Close open files and release open-file table.
         * This may block!
        /*
         * Close open files and release open-file table.
         * This may block!
@@ -262,11 +270,15 @@ proc_exit(struct proc *p)
        /* Close ref SYSV Shared memory*/
        if (p->vm_shm)
                shmexit(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) {
        
        if (SESS_LEADER(p)) {
                register struct session *sp = p->p_session;
 
                if (sp->s_ttyvp) {
+                       struct vnode *ttyvp;
+
                        /*
                         * Controlling process.
                         * Signal foreground pgrp,
                        /*
                         * Controlling process.
                         * Signal foreground pgrp,
@@ -284,9 +296,10 @@ proc_exit(struct proc *p)
                                if (sp->s_ttyvp)
                                        VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
                        }
                                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;
                        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.
                        /*
                         * s_ttyp is not zero'd; we use this to indicate
                         * that the session once had a controlling terminal.
@@ -298,15 +311,22 @@ proc_exit(struct proc *p)
 
        fixjobc(p, p->p_pgrp, 0);
        p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 
        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 KTRACE
        /* 
         * release trace file
         */
        p->p_traceflag = 0;     /* don't trace the vrele() */
-       if (p->p_tracep)
-               vrele(p->p_tracep);
-#endif
+       if (p->p_tracep) {
+               struct vnode *tvp = p->p_tracep;
+               p->p_tracep = NULL;
 
 
+               if (UBCINFOEXISTS(tvp))
+                       ubc_rele(tvp);
+               vrele(tvp);
+       }
+#endif
 
        q = p->p_children.lh_first;
        if (q)          /* only need this if any child is S_ZOMB */
 
        q = p->p_children.lh_first;
        if (q)          /* only need this if any child is S_ZOMB */
@@ -321,7 +341,6 @@ proc_exit(struct proc *p)
                if (q->p_flag & P_TRACED) {
                        q->p_flag &= ~P_TRACED;
                        if (q->sigwait_thread) {
                if (q->p_flag & P_TRACED) {
                        q->p_flag &= ~P_TRACED;
                        if (q->sigwait_thread) {
-                               thread_t sig_shuttle  = getshuttle_thread(q->sigwait_thread);
                                /*
                                 * The sigwait_thread could be stopped at a
                                 * breakpoint. Wake it up to kill.
                                /*
                                 * The sigwait_thread could be stopped at a
                                 * breakpoint. Wake it up to kill.
@@ -329,9 +348,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.
                                 */
                                 * 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);
-                               clear_wait(sig_shuttle, THREAD_INTERRUPTED);
-                               threadsignal(q->sigwait_thread, SIGKILL, 0);
+                               thread_resume((thread_act_t)q->sigwait_thread);
+                               clear_wait(q->sigwait_thread, THREAD_INTERRUPTED);
+                               threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0);
                        }
                        psignal(q, SIGKILL);
                }
                        }
                        psignal(q, SIGKILL);
                }
@@ -403,6 +422,9 @@ proc_exit(struct proc *p)
                FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
        p->p_limit = NULL;
 
                FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
        p->p_limit = NULL;
 
+       /* Free the auditing info */
+       audit_proc_free(p);
+
        /*
         * Finish up by terminating the task
         * and halt this thread (only if a
        /*
         * Finish up by terminating the task
         * and halt this thread (only if a
@@ -412,13 +434,37 @@ proc_exit(struct proc *p)
        //task->proc = NULL;
        set_bsdtask_info(task, NULL);
 
        //task->proc = NULL;
        set_bsdtask_info(task, NULL);
 
+       KNOTE(&p->p_klist, NOTE_EXIT);
+
        /*
         * Notify parent that we're gone.
         */
        /*
         * 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;
+
+               /*
+                * Add child resource usage to parent before giving
+                * zombie to init
+                */
+               ruadd(&p->p_pptr->p_stats->p_cru, p->p_ru);
+
+               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);
+
+       /* mark as a zombie */
        p->p_stat = SZOMB;
 
        /* and now wakeup the parent */
        p->p_stat = SZOMB;
 
        /* and now wakeup the parent */
@@ -476,7 +522,7 @@ owait3(p, uap, retval)
 {
        struct wait4_args *a;
 
 {
        struct wait4_args *a;
 
-       a = (struct wait4_args *)get_bsduthreadarg(current_act);
+       a = (struct wait4_args *)get_bsduthreadarg(current_act());
 
        a->rusage = uap->rusage;
        a->options = uap->options;
 
        a->rusage = uap->rusage;
        a->options = uap->options;
@@ -503,9 +549,9 @@ wait1continue(result)
 
        p = current_proc();
        thread = current_act();
 
        p = current_proc();
        thread = current_act();
-       vt = get_bsduthreadarg(thread);
-       retval = get_bsduthreadrval(thread);
-       wait1((struct proc *)p, (struct wait4_args *)vt, retval, 0);
+       vt = (void *)get_bsduthreadarg(thread);
+       retval = (int *)get_bsduthreadrval(thread);
+       return(wait1((struct proc *)p, (struct wait4_args *)vt, retval, 0));
 }
 
 int
 }
 
 int
@@ -520,6 +566,7 @@ wait1(q, uap, retval, compat)
        register int nfound;
        register struct proc *p, *t;
        int status, error;
        register int nfound;
        register struct proc *p, *t;
        int status, error;
+       struct vnode *tvp;
 
 retry:
        if (uap->pid == 0)
 
 retry:
        if (uap->pid == 0)
@@ -571,6 +618,12 @@ loop:
                        if (p->p_oppid && (t = pfind(p->p_oppid))) {
                                p->p_oppid = 0;
                                proc_reparent(p, t);
                        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;
                                psignal(t, SIGCHLD);
                                wakeup((caddr_t)t);
                                p->p_flag &= ~P_WAITING;
@@ -610,8 +663,10 @@ loop:
                        /*
                         * Release reference to text vnode
                         */
                        /*
                         * 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.
 
                        /*
                         * Finally finished with old proc entry.
@@ -691,8 +746,11 @@ init_process(void)
 {
        register struct proc *p = current_proc();
 
 {
        register struct proc *p = current_proc();
 
-       if (suser(p->p_ucred, &p->p_acflag))
+       AUDIT_MACH_SYSCALL_ENTER(AUE_INITPROCESS);
+       if (suser(p->p_ucred, &p->p_acflag)) {
+               AUDIT_MACH_SYSCALL_EXIT(KERN_NO_ACCESS);
                return(KERN_NO_ACCESS);
                return(KERN_NO_ACCESS);
+       }
 
        if (p->p_pid != 1 && p->p_pgid != p->p_pid)
                enterpgrp(p, p->p_pid, 0);
 
        if (p->p_pid != 1 && p->p_pgid != p->p_pid)
                enterpgrp(p, p->p_pid, 0);
@@ -707,6 +765,7 @@ init_process(void)
        p->p_sibling.le_next = NULL;
        p->p_pptr = kernproc;
 
        p->p_sibling.le_next = NULL;
        p->p_pptr = kernproc;
 
+       AUDIT_MACH_SYSCALL_EXIT(KERN_SUCCESS);
        return(KERN_SUCCESS);
 }
 
        return(KERN_SUCCESS);
 }
 
@@ -727,52 +786,32 @@ process_terminate_self(void)
  * status and rusage for wait().  Check for child processes and orphan them.
  */
 
  * status and rusage for wait().  Check for child processes and orphan them.
  */
 
-void
+int
 vfork_exit(p, rv)
 vfork_exit(p, rv)
-       register struct proc *p;
+       struct proc *p;
        int rv;
 {
        register struct proc *q, *nq;
        int rv;
 {
        register struct proc *q, *nq;
-       thread_t self = current_thread();
-       thread_act_t th_act_self = current_act();
+       thread_act_t self = current_act();
        struct task *task = p->task;
        register int i,s;
        struct uthread *ut;
        struct task *task = p->task;
        register int i,s;
        struct uthread *ut;
+       exception_data_t        code[EXCEPTION_CODE_MAX];
 
 
-       /*
-        * If a thread in this task has already
-        * called exit(), then halt any others
-        * right here.
-        */
-
-        ut = get_bsdthread_info(th_act_self);
-#ifdef FIXME
-        signal_lock(p);
-       while (p->exit_thread != self) {
-               if (sig_try_locked(p) <= 0) {
-                       if (get_threadtask(th_act_self) != task) {
-                                signal_unlock(p);
-                               return;
-                        }
-                       signal_unlock(p);
-                       thread_terminate(th_act_self);
-                       thread_funnel_set(kernel_flock, FALSE);
-                       thread_exception_return();
-                       /* NOTREACHED */
-               }
-               sig_lock_to_exit(p);
-       }
-        signal_unlock(p);
-       if (p->p_pid == 1) {
-               printf("pid 1 exited (signal %d, exit %d)",
-                   WTERMSIG(rv), WEXITSTATUS(rv));
-panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data);
-       }
-#endif /* FIXME */
-
+       ut = get_bsdthread_info(self);
+       if (p->exit_thread) {
+               return(1);
+       } 
+       p->exit_thread = self;
+       
        s = splsched();
        p->p_flag |= P_WEXIT;
        splx(s);
        s = splsched();
        p->p_flag |= P_WEXIT;
        splx(s);
+
+       code[0] = 0xFF000001;                   /* Set terminate code */
+       code[1] = p->p_pid;                             /* Pass out the pid     */
+       (void)sys_perf_notify(p->task, &code, 2);       /* Notify the perf server */
+
        /*
         * Remove proc from allproc queue and from pidhash chain.
         * Need to do this before we do anything that can block.
        /*
         * Remove proc from allproc queue and from pidhash chain.
         * Need to do this before we do anything that can block.
@@ -780,6 +819,7 @@ panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data);
         * in partially cleaned state.
         */
        LIST_REMOVE(p, p_list);
         * in partially cleaned state.
         */
        LIST_REMOVE(p, p_list);
+       LIST_INSERT_HEAD(&zombproc, p, p_list); /* Place onto zombproc. */
        LIST_REMOVE(p, p_hash);
        /*
         * If parent is waiting for us to exit or exec,
        LIST_REMOVE(p, p_hash);
        /*
         * If parent is waiting for us to exit or exec,
@@ -789,20 +829,19 @@ panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data);
        p->p_sigignore = ~0;
        p->p_siglist = 0;
 
        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);
 
        p->p_xstat = rv;
 
        vproc_exit(p);
+       return(0);
 }
 
 void 
 vproc_exit(struct proc *p)
 {
 }
 
 void 
 vproc_exit(struct proc *p)
 {
-       register struct proc *q, *nq;
-       thread_t self = current_thread();
-       thread_act_t th_act_self = current_act();
+       register struct proc *q, *nq, *pp;
        struct task *task = p->task;
        register int i,s;
        boolean_t funnel_state;
        struct task *task = p->task;
        register int i,s;
        boolean_t funnel_state;
@@ -816,14 +855,12 @@ vproc_exit(struct proc *p)
         */
        fdfree(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) {
        if (SESS_LEADER(p)) {
                register struct session *sp = p->p_session;
 
                if (sp->s_ttyvp) {
+                       struct vnode *ttyvp;
+
                        /*
                         * Controlling process.
                         * Signal foreground pgrp,
                        /*
                         * Controlling process.
                         * Signal foreground pgrp,
@@ -841,9 +878,10 @@ vproc_exit(struct proc *p)
                                if (sp->s_ttyvp)
                                        VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
                        }
                                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;
                        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.
                        /*
                         * s_ttyp is not zero'd; we use this to indicate
                         * that the session once had a controlling terminal.
@@ -855,13 +893,20 @@ vproc_exit(struct proc *p)
 
        fixjobc(p, p->p_pgrp, 0);
        p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 
        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 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;
+
+               if (UBCINFOEXISTS(tvp))
+                       ubc_rele(tvp);
+               vrele(tvp);
+       }
 #endif
 
        q = p->p_children.lh_first;
 #endif
 
        q = p->p_children.lh_first;
@@ -877,7 +922,6 @@ vproc_exit(struct proc *p)
                if (q->p_flag & P_TRACED) {
                        q->p_flag &= ~P_TRACED;
                        if (q->sigwait_thread) {
                if (q->p_flag & P_TRACED) {
                        q->p_flag &= ~P_TRACED;
                        if (q->sigwait_thread) {
-                               thread_t sig_shuttle  = getshuttle_thread(q->sigwait_thread);
                                /*
                                 * The sigwait_thread could be stopped at a
                                 * breakpoint. Wake it up to kill.
                                /*
                                 * The sigwait_thread could be stopped at a
                                 * breakpoint. Wake it up to kill.
@@ -885,9 +929,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.
                                 */
                                 * 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);
-                               clear_wait(sig_shuttle, THREAD_INTERRUPTED);
-                               threadsignal(q->sigwait_thread, SIGKILL, 0);
+                               thread_resume((thread_act_t)q->sigwait_thread);
+                               clear_wait(q->sigwait_thread, THREAD_INTERRUPTED);
+                               threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0);
                        }
                        psignal(q, SIGKILL);
                }
                        }
                        psignal(q, SIGKILL);
                }
@@ -971,10 +1015,16 @@ vproc_exit(struct proc *p)
        /*
         * Notify parent that we're gone.
         */
        /*
         * 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);
 
        psignal(p->p_pptr, SIGCHLD);
 
-       /* Place onto zombproc. */
-       LIST_INSERT_HEAD(&zombproc, p, p_list);
+       /* mark as a zombie */
        p->p_stat = SZOMB;
 
        /* and now wakeup the parent */
        p->p_stat = SZOMB;
 
        /* and now wakeup the parent */