From owner-svn-src-all@FreeBSD.ORG Mon Jun 8 15:26:10 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 69523106566B; Mon, 8 Jun 2009 15:26:10 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 13FDE8FC0C; Mon, 8 Jun 2009 15:26:10 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n58FQ9xB033574; Mon, 8 Jun 2009 15:26:09 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n58FQ9F8033573; Mon, 8 Jun 2009 15:26:09 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200906081526.n58FQ9F8033573@svn.freebsd.org> From: Robert Watson Date: Mon, 8 Jun 2009 15:26:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193723 - head/sys/kern X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Jun 2009 15:26:11 -0000 Author: rwatson Date: Mon Jun 8 15:26:09 2009 New Revision: 193723 URL: http://svn.freebsd.org/changeset/base/193723 Log: Move zombie-reaping code out of kern_wait() and into its own function, proc_reap(). Reviewed by: jhb MFC after: 3 days Sponsored by: Google, Inc. Modified: head/sys/kern/kern_exit.c Modified: head/sys/kern/kern_exit.c ============================================================================== --- head/sys/kern/kern_exit.c Mon Jun 8 15:17:36 2009 (r193722) +++ head/sys/kern/kern_exit.c Mon Jun 8 15:26:09 2009 (r193723) @@ -682,11 +682,130 @@ wait4(struct thread *td, struct wait_arg return (error); } +/* + * Reap the remains of a zombie process and optionally return status and + * rusage. Asserts and will release both the proctree_lock and the process + * lock as part of its work. + */ +static void +proc_reap(struct thread *td, struct proc *p, int *status, int options, + struct rusage *rusage) +{ + INIT_VPROCG(P_TO_VPROCG(p)); + struct proc *q, *t; + + sx_assert(&proctree_lock, SA_XLOCKED); + PROC_LOCK_ASSERT(p, MA_OWNED); + PROC_SLOCK_ASSERT(p, MA_OWNED); + KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE")); + + q = td->td_proc; + if (rusage) { + *rusage = p->p_ru; + calcru(p, &rusage->ru_utime, &rusage->ru_stime); + } + PROC_SUNLOCK(p); + td->td_retval[0] = p->p_pid; + if (status) + *status = p->p_xstat; /* convert to int */ + if (options & WNOWAIT) { + /* + * Only poll, returning the status. Caller does not wish to + * release the proc struct just yet. + */ + PROC_UNLOCK(p); + sx_xunlock(&proctree_lock); + return; + } + + PROC_LOCK(q); + sigqueue_take(p->p_ksi); + PROC_UNLOCK(q); + PROC_UNLOCK(p); + + /* + * If we got the child via a ptrace 'attach', we need to give it back + * to the old parent. + */ + if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { + PROC_LOCK(p); + p->p_oppid = 0; + proc_reparent(p, t); + PROC_UNLOCK(p); + tdsignal(t, NULL, SIGCHLD, p->p_ksi); + wakeup(t); + cv_broadcast(&p->p_pwait); + PROC_UNLOCK(t); + sx_xunlock(&proctree_lock); + return; + } + + /* + * Remove other references to this process to ensure we have an + * exclusive reference. + */ + sx_xlock(&allproc_lock); + LIST_REMOVE(p, p_list); /* off zombproc */ + sx_xunlock(&allproc_lock); + LIST_REMOVE(p, p_sibling); + leavepgrp(p); + sx_xunlock(&proctree_lock); + + /* + * As a side effect of this lock, we know that all other writes to + * this proc are visible now, so no more locking is needed for p. + */ + PROC_LOCK(p); + p->p_xstat = 0; /* XXX: why? */ + PROC_UNLOCK(p); + PROC_LOCK(q); + ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, &p->p_rux); + PROC_UNLOCK(q); + + /* + * Decrement the count of procs running with this uid. + */ + (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); + + /* + * Free credentials, arguments, and sigacts. + */ + crfree(p->p_ucred); + p->p_ucred = NULL; + pargs_drop(p->p_args); + p->p_args = NULL; + sigacts_free(p->p_sigacts); + p->p_sigacts = NULL; + + /* + * Do any thread-system specific cleanups. + */ + thread_wait(p); + + /* + * Give vm and machine-dependent layer a chance to free anything that + * cpu_exit couldn't release while still running in process context. + */ + vm_waitproc(p); +#ifdef MAC + mac_proc_destroy(p); +#endif + KASSERT(FIRST_THREAD_IN_PROC(p), + ("proc_reap: no residual thread!")); + uma_zfree(proc_zone, p); + sx_xlock(&allproc_lock); + nprocs--; +#ifdef VIMAGE + vprocg->nprocs--; +#endif + sx_xunlock(&allproc_lock); +} + int kern_wait(struct thread *td, pid_t pid, int *status, int options, struct rusage *rusage) { - struct proc *p, *q, *t; + struct proc *p, *q; int error, nfound; AUDIT_ARG(pid, pid); @@ -736,111 +855,7 @@ loop: nfound++; PROC_SLOCK(p); if (p->p_state == PRS_ZOMBIE) { - INIT_VPROCG(P_TO_VPROCG(p)); - if (rusage) { - *rusage = p->p_ru; - calcru(p, &rusage->ru_utime, &rusage->ru_stime); - } - PROC_SUNLOCK(p); - td->td_retval[0] = p->p_pid; - if (status) - *status = p->p_xstat; /* convert to int */ - if (options & WNOWAIT) { - - /* - * Only poll, returning the status. - * Caller does not wish to release the proc - * struct just yet. - */ - PROC_UNLOCK(p); - sx_xunlock(&proctree_lock); - return (0); - } - - PROC_LOCK(q); - sigqueue_take(p->p_ksi); - PROC_UNLOCK(q); - PROC_UNLOCK(p); - - /* - * If we got the child via a ptrace 'attach', - * we need to give it back to the old parent. - */ - if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { - PROC_LOCK(p); - p->p_oppid = 0; - proc_reparent(p, t); - PROC_UNLOCK(p); - tdsignal(t, NULL, SIGCHLD, p->p_ksi); - wakeup(t); - cv_broadcast(&p->p_pwait); - PROC_UNLOCK(t); - sx_xunlock(&proctree_lock); - return (0); - } - - /* - * Remove other references to this process to ensure - * we have an exclusive reference. - */ - sx_xlock(&allproc_lock); - LIST_REMOVE(p, p_list); /* off zombproc */ - sx_xunlock(&allproc_lock); - LIST_REMOVE(p, p_sibling); - leavepgrp(p); - sx_xunlock(&proctree_lock); - - /* - * As a side effect of this lock, we know that - * all other writes to this proc are visible now, so - * no more locking is needed for p. - */ - PROC_LOCK(p); - p->p_xstat = 0; /* XXX: why? */ - PROC_UNLOCK(p); - PROC_LOCK(q); - ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, - &p->p_rux); - PROC_UNLOCK(q); - - /* - * Decrement the count of procs running with this uid. - */ - (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); - - /* - * Free credentials, arguments, and sigacts. - */ - crfree(p->p_ucred); - p->p_ucred = NULL; - pargs_drop(p->p_args); - p->p_args = NULL; - sigacts_free(p->p_sigacts); - p->p_sigacts = NULL; - - /* - * Do any thread-system specific cleanups. - */ - thread_wait(p); - - /* - * Give vm and machine-dependent layer a chance - * to free anything that cpu_exit couldn't - * release while still running in process context. - */ - vm_waitproc(p); -#ifdef MAC - mac_proc_destroy(p); -#endif - KASSERT(FIRST_THREAD_IN_PROC(p), - ("kern_wait: no residual thread!")); - uma_zfree(proc_zone, p); - sx_xlock(&allproc_lock); - nprocs--; -#ifdef VIMAGE - vprocg->nprocs--; -#endif - sx_xunlock(&allproc_lock); + proc_reap(td, p, status, options, rusage); return (0); } if ((p->p_flag & P_STOPPED_SIG) &&