The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_exit.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: kern_exit.c,v 1.210 2022/12/29 01:36:36 guenther Exp $        */
    2 /*      $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1991, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  * (c) UNIX System Laboratories, Inc.
    8  * All or some portions of this file are derived from material licensed
    9  * to the University of California by American Telephone and Telegraph
   10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   11  * the permission of UNIX System Laboratories, Inc.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/proc.h>
   43 #include <sys/time.h>
   44 #include <sys/resource.h>
   45 #include <sys/wait.h>
   46 #include <sys/vnode.h>
   47 #include <sys/malloc.h>
   48 #include <sys/resourcevar.h>
   49 #include <sys/ptrace.h>
   50 #include <sys/acct.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/signalvar.h>
   53 #include <sys/sched.h>
   54 #include <sys/ktrace.h>
   55 #include <sys/pool.h>
   56 #include <sys/mutex.h>
   57 #ifdef SYSVSEM
   58 #include <sys/sem.h>
   59 #endif
   60 #include <sys/witness.h>
   61 
   62 #include <sys/mount.h>
   63 #include <sys/syscallargs.h>
   64 
   65 #include <uvm/uvm_extern.h>
   66 
   67 #include "kcov.h"
   68 #if NKCOV > 0
   69 #include <sys/kcov.h>
   70 #endif
   71 
   72 void    proc_finish_wait(struct proc *, struct proc *);
   73 void    process_clear_orphan(struct process *);
   74 void    process_zap(struct process *);
   75 void    proc_free(struct proc *);
   76 void    unveil_destroy(struct process *ps);
   77 
   78 /*
   79  * exit --
   80  *      Death of process.
   81  */
   82 int
   83 sys_exit(struct proc *p, void *v, register_t *retval)
   84 {
   85         struct sys_exit_args /* {
   86                 syscallarg(int) rval;
   87         } */ *uap = v;
   88 
   89         exit1(p, SCARG(uap, rval), 0, EXIT_NORMAL);
   90         /* NOTREACHED */
   91         return (0);
   92 }
   93 
   94 int
   95 sys___threxit(struct proc *p, void *v, register_t *retval)
   96 {
   97         struct sys___threxit_args /* {
   98                 syscallarg(pid_t *) notdead;
   99         } */ *uap = v;
  100 
  101         if (SCARG(uap, notdead) != NULL) {
  102                 pid_t zero = 0;
  103                 if (copyout(&zero, SCARG(uap, notdead), sizeof(zero)))
  104                         psignal(p, SIGSEGV);
  105         }
  106         exit1(p, 0, 0, EXIT_THREAD);
  107 
  108         return (0);
  109 }
  110 
  111 /*
  112  * Exit: deallocate address space and other resources, change proc state
  113  * to zombie, and unlink proc from allproc and parent's lists.  Save exit
  114  * status and rusage for wait().  Check for child processes and orphan them.
  115  */
  116 void
  117 exit1(struct proc *p, int xexit, int xsig, int flags)
  118 {
  119         struct process *pr, *qr, *nqr;
  120         struct rusage *rup;
  121         int s;
  122 
  123         atomic_setbits_int(&p->p_flag, P_WEXIT);
  124 
  125         pr = p->p_p;
  126 
  127         /* single-threaded? */
  128         if (!P_HASSIBLING(p)) {
  129                 flags = EXIT_NORMAL;
  130         } else {
  131                 /* nope, multi-threaded */
  132                 if (flags == EXIT_NORMAL)
  133                         single_thread_set(p, SINGLE_EXIT, 1);
  134                 else if (flags == EXIT_THREAD)
  135                         single_thread_check(p, 0);
  136         }
  137 
  138         if (flags == EXIT_NORMAL && !(pr->ps_flags & PS_EXITING)) {
  139                 if (pr->ps_pid == 1)
  140                         panic("init died (signal %d, exit %d)", xsig, xexit);
  141 
  142                 atomic_setbits_int(&pr->ps_flags, PS_EXITING);
  143                 pr->ps_xexit = xexit;
  144                 pr->ps_xsig  = xsig;
  145 
  146                 /*
  147                  * If parent is waiting for us to exit or exec, PS_PPWAIT
  148                  * is set; we wake up the parent early to avoid deadlock.
  149                  */
  150                 if (pr->ps_flags & PS_PPWAIT) {
  151                         atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT);
  152                         atomic_clearbits_int(&pr->ps_pptr->ps_flags,
  153                             PS_ISPWAIT);
  154                         wakeup(pr->ps_pptr);
  155                 }
  156         }
  157 
  158         /* unlink ourselves from the active threads */
  159         SCHED_LOCK(s);
  160         TAILQ_REMOVE(&pr->ps_threads, p, p_thr_link);
  161         SCHED_UNLOCK(s);
  162         if ((p->p_flag & P_THREAD) == 0) {
  163                 /* main thread gotta wait because it has the pid, et al */
  164                 while (pr->ps_refcnt > 1)
  165                         tsleep_nsec(&pr->ps_threads, PWAIT, "thrdeath", INFSLP);
  166                 if (pr->ps_flags & PS_PROFIL)
  167                         stopprofclock(pr);
  168         }
  169 
  170         rup = pr->ps_ru;
  171         if (rup == NULL) {
  172                 rup = pool_get(&rusage_pool, PR_WAITOK | PR_ZERO);
  173                 if (pr->ps_ru == NULL) {
  174                         pr->ps_ru = rup;
  175                 } else {
  176                         pool_put(&rusage_pool, rup);
  177                         rup = pr->ps_ru;
  178                 }
  179         }
  180         p->p_siglist = 0;
  181         if ((p->p_flag & P_THREAD) == 0)
  182                 pr->ps_siglist = 0;
  183 
  184         kqpoll_exit();
  185 
  186 #if NKCOV > 0
  187         kcov_exit(p);
  188 #endif
  189 
  190         if ((p->p_flag & P_THREAD) == 0) {
  191                 sigio_freelist(&pr->ps_sigiolst);
  192 
  193                 /* close open files and release open-file table */
  194                 fdfree(p);
  195 
  196                 cancel_all_itimers();
  197 
  198                 timeout_del(&pr->ps_rucheck_to);
  199 #ifdef SYSVSEM
  200                 semexit(pr);
  201 #endif
  202                 killjobc(pr);
  203 #ifdef ACCOUNTING
  204                 acct_process(p);
  205 #endif
  206 
  207 #ifdef KTRACE
  208                 /* release trace file */
  209                 if (pr->ps_tracevp)
  210                         ktrcleartrace(pr);
  211 #endif
  212 
  213                 unveil_destroy(pr);
  214 
  215                 /*
  216                  * If parent has the SAS_NOCLDWAIT flag set, we're not
  217                  * going to become a zombie.
  218                  */
  219                 if (pr->ps_pptr->ps_sigacts->ps_sigflags & SAS_NOCLDWAIT)
  220                         atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE);
  221         }
  222 
  223         p->p_fd = NULL;         /* zap the thread's copy */
  224 
  225         /*
  226          * Remove proc from pidhash chain and allproc so looking
  227          * it up won't work.  We will put the proc on the
  228          * deadproc list later (using the p_hash member), and
  229          * wake up the reaper when we do.  If this is the last
  230          * thread of a process that isn't PS_NOZOMBIE, we'll put
  231          * the process on the zombprocess list below.
  232          */
  233         /*
  234          * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP!
  235          */
  236         p->p_stat = SDEAD;
  237 
  238         LIST_REMOVE(p, p_hash);
  239         LIST_REMOVE(p, p_list);
  240 
  241         if ((p->p_flag & P_THREAD) == 0) {
  242                 LIST_REMOVE(pr, ps_hash);
  243                 LIST_REMOVE(pr, ps_list);
  244 
  245                 if ((pr->ps_flags & PS_NOZOMBIE) == 0)
  246                         LIST_INSERT_HEAD(&zombprocess, pr, ps_list);
  247                 else {
  248                         /*
  249                          * Not going to be a zombie, so it's now off all
  250                          * the lists scanned by ispidtaken(), so block
  251                          * fast reuse of the pid now.
  252                          */
  253                         freepid(pr->ps_pid);
  254                 }
  255 
  256                 /*
  257                  * Reparent children to their original parent, in case
  258                  * they were being traced, or to init(8).
  259                  */
  260                 qr = LIST_FIRST(&pr->ps_children);
  261                 if (qr)         /* only need this if any child is S_ZOMB */
  262                         wakeup(initprocess);
  263                 for (; qr != NULL; qr = nqr) {
  264                         nqr = LIST_NEXT(qr, ps_sibling);
  265                         /*
  266                          * Traced processes are killed since their
  267                          * existence means someone is screwing up.
  268                          */
  269                         if (qr->ps_flags & PS_TRACED &&
  270                             !(qr->ps_flags & PS_EXITING)) {
  271                                 process_untrace(qr);
  272 
  273                                 /*
  274                                  * If single threading is active,
  275                                  * direct the signal to the active
  276                                  * thread to avoid deadlock.
  277                                  */
  278                                 if (qr->ps_single)
  279                                         ptsignal(qr->ps_single, SIGKILL,
  280                                             STHREAD);
  281                                 else
  282                                         prsignal(qr, SIGKILL);
  283                         } else {
  284                                 process_reparent(qr, initprocess);
  285                         }
  286                 }
  287 
  288                 /*
  289                  * Make sure orphans won't remember the exiting process.
  290                  */
  291                 while ((qr = LIST_FIRST(&pr->ps_orphans)) != NULL) {
  292                         KASSERT(qr->ps_oppid == pr->ps_pid);
  293                         qr->ps_oppid = 0;
  294                         process_clear_orphan(qr);
  295                 }
  296         }
  297 
  298         /* add thread's accumulated rusage into the process's total */
  299         ruadd(rup, &p->p_ru);
  300         tuagg(pr, p);
  301 
  302         /*
  303          * clear %cpu usage during swap
  304          */
  305         p->p_pctcpu = 0;
  306 
  307         if ((p->p_flag & P_THREAD) == 0) {
  308                 /*
  309                  * Final thread has died, so add on our children's rusage
  310                  * and calculate the total times
  311                  */
  312                 calcru(&pr->ps_tu, &rup->ru_utime, &rup->ru_stime, NULL);
  313                 ruadd(rup, &pr->ps_cru);
  314 
  315                 /*
  316                  * Notify parent that we're gone.  If we're not going to
  317                  * become a zombie, reparent to process 1 (init) so that
  318                  * we can wake our original parent to possibly unblock
  319                  * wait4() to return ECHILD.
  320                  */
  321                 if (pr->ps_flags & PS_NOZOMBIE) {
  322                         struct process *ppr = pr->ps_pptr;
  323                         process_reparent(pr, initprocess);
  324                         wakeup(ppr);
  325                 }
  326         }
  327 
  328         /* just a thread? detach it from its process */
  329         if (p->p_flag & P_THREAD) {
  330                 /* scheduler_wait_hook(pr->ps_mainproc, p); XXX */
  331                 if (--pr->ps_refcnt == 1)
  332                         wakeup(&pr->ps_threads);
  333                 KASSERT(pr->ps_refcnt > 0);
  334         }
  335 
  336         /* Release the thread's read reference of resource limit structure. */
  337         if (p->p_limit != NULL) {
  338                 struct plimit *limit;
  339 
  340                 limit = p->p_limit;
  341                 p->p_limit = NULL;
  342                 lim_free(limit);
  343         }
  344 
  345         /*
  346          * Other substructures are freed from reaper and wait().
  347          */
  348 
  349         /*
  350          * Finally, call machine-dependent code to switch to a new
  351          * context (possibly the idle context).  Once we are no longer
  352          * using the dead process's vmspace and stack, exit2() will be
  353          * called to schedule those resources to be released by the
  354          * reaper thread.
  355          *
  356          * Note that cpu_exit() will end with a call equivalent to
  357          * cpu_switch(), finishing our execution (pun intended).
  358          */
  359         uvmexp.swtch++;
  360         cpu_exit(p);
  361         panic("cpu_exit returned");
  362 }
  363 
  364 /*
  365  * Locking of this proclist is special; it's accessed in a
  366  * critical section of process exit, and thus locking it can't
  367  * modify interrupt state.  We use a simple spin lock for this
  368  * proclist.  We use the p_hash member to linkup to deadproc.
  369  */
  370 struct mutex deadproc_mutex =
  371     MUTEX_INITIALIZER_FLAGS(IPL_NONE, "deadproc", MTX_NOWITNESS);
  372 struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc);
  373 
  374 /*
  375  * We are called from cpu_exit() once it is safe to schedule the
  376  * dead process's resources to be freed.
  377  *
  378  * NOTE: One must be careful with locking in this routine.  It's
  379  * called from a critical section in machine-dependent code, so
  380  * we should refrain from changing any interrupt state.
  381  *
  382  * We lock the deadproc list, place the proc on that list (using
  383  * the p_hash member), and wake up the reaper.
  384  */
  385 void
  386 exit2(struct proc *p)
  387 {
  388         mtx_enter(&deadproc_mutex);
  389         LIST_INSERT_HEAD(&deadproc, p, p_hash);
  390         mtx_leave(&deadproc_mutex);
  391 
  392         wakeup(&deadproc);
  393 }
  394 
  395 void
  396 proc_free(struct proc *p)
  397 {
  398         crfree(p->p_ucred);
  399         pool_put(&proc_pool, p);
  400         nthreads--;
  401 }
  402 
  403 /*
  404  * Process reaper.  This is run by a kernel thread to free the resources
  405  * of a dead process.  Once the resources are free, the process becomes
  406  * a zombie, and the parent is allowed to read the undead's status.
  407  */
  408 void
  409 reaper(void *arg)
  410 {
  411         struct proc *p;
  412 
  413         KERNEL_UNLOCK();
  414 
  415         SCHED_ASSERT_UNLOCKED();
  416 
  417         for (;;) {
  418                 mtx_enter(&deadproc_mutex);
  419                 while ((p = LIST_FIRST(&deadproc)) == NULL)
  420                         msleep_nsec(&deadproc, &deadproc_mutex, PVM, "reaper",
  421                             INFSLP);
  422 
  423                 /* Remove us from the deadproc list. */
  424                 LIST_REMOVE(p, p_hash);
  425                 mtx_leave(&deadproc_mutex);
  426 
  427                 WITNESS_THREAD_EXIT(p);
  428 
  429                 KERNEL_LOCK();
  430 
  431                 /*
  432                  * Free the VM resources we're still holding on to.
  433                  * We must do this from a valid thread because doing
  434                  * so may block.
  435                  */
  436                 uvm_uarea_free(p);
  437                 p->p_vmspace = NULL;            /* zap the thread's copy */
  438 
  439                 if (p->p_flag & P_THREAD) {
  440                         /* Just a thread */
  441                         proc_free(p);
  442                 } else {
  443                         struct process *pr = p->p_p;
  444 
  445                         /* Release the rest of the process's vmspace */
  446                         uvm_exit(pr);
  447 
  448                         if ((pr->ps_flags & PS_NOZOMBIE) == 0) {
  449                                 /* Process is now a true zombie. */
  450                                 atomic_setbits_int(&pr->ps_flags, PS_ZOMBIE);
  451                         }
  452 
  453                         /* Notify listeners of our demise and clean up. */
  454                         knote_processexit(pr);
  455 
  456                         if (pr->ps_flags & PS_ZOMBIE) {
  457                                 /* Post SIGCHLD and wake up parent. */
  458                                 prsignal(pr->ps_pptr, SIGCHLD);
  459                                 wakeup(pr->ps_pptr);
  460                         } else {
  461                                 /* No one will wait for us, just zap it. */
  462                                 process_zap(pr);
  463                         }
  464                 }
  465 
  466                 KERNEL_UNLOCK();
  467         }
  468 }
  469 
  470 int
  471 dowait6(struct proc *q, idtype_t idtype, id_t id, int *statusp, int options,
  472     struct rusage *rusage, siginfo_t *info, register_t *retval)
  473 {
  474         int nfound;
  475         struct process *pr;
  476         struct proc *p;
  477         int error;
  478 
  479         if (info != NULL)
  480                 memset(info, 0, sizeof(*info));
  481 
  482 loop:
  483         nfound = 0;
  484         LIST_FOREACH(pr, &q->p_p->ps_children, ps_sibling) {
  485                 if ((pr->ps_flags & PS_NOZOMBIE) ||
  486                     (idtype == P_PID && id != pr->ps_pid) ||
  487                     (idtype == P_PGID && id != pr->ps_pgid))
  488                         continue;
  489 
  490                 p = pr->ps_mainproc;
  491 
  492                 nfound++;
  493                 if ((options & WEXITED) && (pr->ps_flags & PS_ZOMBIE)) {
  494                         *retval = pr->ps_pid;
  495                         if (info != NULL) {
  496                                 info->si_pid = pr->ps_pid;
  497                                 info->si_uid = pr->ps_ucred->cr_uid;
  498                                 info->si_signo = SIGCHLD;
  499                                 if (pr->ps_xsig == 0) {
  500                                         info->si_code = CLD_EXITED;
  501                                         info->si_status = pr->ps_xexit;
  502                                 } else if (WCOREDUMP(pr->ps_xsig)) {
  503                                         info->si_code = CLD_DUMPED;
  504                                         info->si_status = _WSTATUS(pr->ps_xsig);
  505                                 } else {
  506                                         info->si_code = CLD_KILLED;
  507                                         info->si_status = _WSTATUS(pr->ps_xsig);
  508                                 }
  509                         }
  510 
  511                         if (statusp != NULL)
  512                                 *statusp = W_EXITCODE(pr->ps_xexit,
  513                                     pr->ps_xsig);
  514                         if (rusage != NULL)
  515                                 memcpy(rusage, pr->ps_ru, sizeof(*rusage));
  516                         if ((options & WNOWAIT) == 0)
  517                                 proc_finish_wait(q, p);
  518                         return (0);
  519                 }
  520                 if ((options & WTRAPPED) &&
  521                     pr->ps_flags & PS_TRACED &&
  522                     (pr->ps_flags & PS_WAITED) == 0 && pr->ps_single &&
  523                     pr->ps_single->p_stat == SSTOP &&
  524                     (pr->ps_single->p_flag & P_SUSPSINGLE) == 0) {
  525                         if (single_thread_wait(pr, 0))
  526                                 goto loop;
  527 
  528                         if ((options & WNOWAIT) == 0)
  529                                 atomic_setbits_int(&pr->ps_flags, PS_WAITED);
  530 
  531                         *retval = pr->ps_pid;
  532                         if (info != NULL) {
  533                                 info->si_pid = pr->ps_pid;
  534                                 info->si_uid = pr->ps_ucred->cr_uid;
  535                                 info->si_signo = SIGCHLD;
  536                                 info->si_code = CLD_TRAPPED;
  537                                 info->si_status = pr->ps_xsig;
  538                         }
  539 
  540                         if (statusp != NULL)
  541                                 *statusp = W_STOPCODE(pr->ps_xsig);
  542                         if (rusage != NULL)
  543                                 memset(rusage, 0, sizeof(*rusage));
  544                         return (0);
  545                 }
  546                 if (p->p_stat == SSTOP &&
  547                     (pr->ps_flags & PS_WAITED) == 0 &&
  548                     (p->p_flag & P_SUSPSINGLE) == 0 &&
  549                     (pr->ps_flags & PS_TRACED ||
  550                     options & WUNTRACED)) {
  551                         if ((options & WNOWAIT) == 0)
  552                                 atomic_setbits_int(&pr->ps_flags, PS_WAITED);
  553 
  554                         *retval = pr->ps_pid;
  555                         if (info != 0) {
  556                                 info->si_pid = pr->ps_pid;
  557                                 info->si_uid = pr->ps_ucred->cr_uid;
  558                                 info->si_signo = SIGCHLD;
  559                                 info->si_code = CLD_STOPPED;
  560                                 info->si_status = pr->ps_xsig;
  561                         }
  562 
  563                         if (statusp != NULL)
  564                                 *statusp = W_STOPCODE(pr->ps_xsig);
  565                         if (rusage != NULL)
  566                                 memset(rusage, 0, sizeof(*rusage));
  567                         return (0);
  568                 }
  569                 if ((options & WCONTINUED) && (p->p_flag & P_CONTINUED)) {
  570                         if ((options & WNOWAIT) == 0)
  571                                 atomic_clearbits_int(&p->p_flag, P_CONTINUED);
  572 
  573                         *retval = pr->ps_pid;
  574                         if (info != NULL) {
  575                                 info->si_pid = pr->ps_pid;
  576                                 info->si_uid = pr->ps_ucred->cr_uid;
  577                                 info->si_signo = SIGCHLD;
  578                                 info->si_code = CLD_CONTINUED;
  579                                 info->si_status = SIGCONT;
  580                         }
  581 
  582                         if (statusp != NULL)
  583                                 *statusp = _WCONTINUED;
  584                         if (rusage != NULL)
  585                                 memset(rusage, 0, sizeof(*rusage));
  586                         return (0);
  587                 }
  588         }
  589         /*
  590          * Look in the orphans list too, to allow the parent to
  591          * collect its child's exit status even if child is being
  592          * debugged.
  593          *
  594          * Debugger detaches from the parent upon successful
  595          * switch-over from parent to child.  At this point due to
  596          * re-parenting the parent loses the child to debugger and a
  597          * wait4(2) call would report that it has no children to wait
  598          * for.  By maintaining a list of orphans we allow the parent
  599          * to successfully wait until the child becomes a zombie.
  600          */
  601         if (nfound == 0) {
  602                 LIST_FOREACH(pr, &q->p_p->ps_orphans, ps_orphan) {
  603                         if ((pr->ps_flags & PS_NOZOMBIE) ||
  604                             (idtype == P_PID && id != pr->ps_pid) ||
  605                             (idtype == P_PGID && id != pr->ps_pgid))
  606                                 continue;
  607                         nfound++;
  608                         break;
  609                 }
  610         }
  611         if (nfound == 0)
  612                 return (ECHILD);
  613         if (options & WNOHANG) {
  614                 *retval = 0;
  615                 return (0);
  616         }
  617         if ((error = tsleep_nsec(q->p_p, PWAIT | PCATCH, "wait", INFSLP)) != 0)
  618                 return (error);
  619         goto loop;
  620 }
  621 
  622 int
  623 sys_wait4(struct proc *q, void *v, register_t *retval)
  624 {
  625         struct sys_wait4_args /* {
  626                 syscallarg(pid_t) pid;
  627                 syscallarg(int *) status;
  628                 syscallarg(int) options;
  629                 syscallarg(struct rusage *) rusage;
  630         } */ *uap = v;
  631         struct rusage ru;
  632         pid_t pid = SCARG(uap, pid);
  633         int options = SCARG(uap, options);
  634         int status, error;
  635         idtype_t idtype;
  636         id_t id;
  637 
  638         if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG|WCONTINUED))
  639                 return (EINVAL);
  640         options |= WEXITED | WTRAPPED;
  641 
  642         if (SCARG(uap, pid) == WAIT_MYPGRP) {
  643                 idtype = P_PGID;
  644                 id = q->p_p->ps_pgid;
  645         } else if (SCARG(uap, pid) == WAIT_ANY) {
  646                 idtype = P_ALL;
  647                 id = 0;
  648         } else if (pid < 0) {
  649                 idtype = P_PGID;
  650                 id = -pid;
  651         } else {
  652                 idtype = P_PID;
  653                 id = pid;
  654         }
  655 
  656         error = dowait6(q, idtype, id,
  657             SCARG(uap, status) ? &status : NULL, options,
  658             SCARG(uap, rusage) ? &ru : NULL, NULL, retval);
  659         if (error == 0 && *retval > 0 && SCARG(uap, status)) {
  660                 error = copyout(&status, SCARG(uap, status), sizeof(status));
  661         }
  662         if (error == 0 && *retval > 0 && SCARG(uap, rusage)) {
  663                 error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
  664 #ifdef KTRACE
  665                 if (error == 0 && KTRPOINT(q, KTR_STRUCT))
  666                         ktrrusage(q, &ru);
  667 #endif
  668         }
  669         return (error);
  670 }
  671 
  672 int
  673 sys_waitid(struct proc *q, void *v, register_t *retval)
  674 {
  675         struct sys_waitid_args /* {
  676                 syscallarg(idtype_t) idtype;
  677                 syscallarg(id_t) id;
  678                 syscallarg(siginfo_t) info;
  679                 syscallarg(int) options;
  680         } */ *uap = v;
  681         siginfo_t info;
  682         idtype_t idtype = SCARG(uap, idtype);
  683         int options = SCARG(uap, options);
  684         int error;
  685 
  686         if (options &~ (WSTOPPED|WCONTINUED|WEXITED|WTRAPPED|WNOHANG|WNOWAIT))
  687                 return (EINVAL);
  688         if ((options & (WSTOPPED|WCONTINUED|WEXITED|WTRAPPED)) == 0)
  689                 return (EINVAL);
  690         if (idtype != P_ALL && idtype != P_PID && idtype != P_PGID)
  691                 return (EINVAL);
  692 
  693         error = dowait6(q, idtype, SCARG(uap, id), NULL,
  694             options, NULL, &info, retval);
  695         if (error == 0) {
  696                 error = copyout(&info, SCARG(uap, info), sizeof(info));
  697 #ifdef KTRACE
  698                 if (error == 0 && KTRPOINT(q, KTR_STRUCT))
  699                         ktrsiginfo(q, &info);
  700 #endif
  701         }
  702         if (error == 0)
  703                 *retval = 0;
  704         return (error);
  705 }
  706 
  707 void
  708 proc_finish_wait(struct proc *waiter, struct proc *p)
  709 {
  710         struct process *pr, *tr;
  711         struct rusage *rup;
  712 
  713         /*
  714          * If we got the child via a ptrace 'attach',
  715          * we need to give it back to the old parent.
  716          */
  717         pr = p->p_p;
  718         if (pr->ps_oppid != 0 && (pr->ps_oppid != pr->ps_pptr->ps_pid) &&
  719            (tr = prfind(pr->ps_oppid))) {
  720                 pr->ps_oppid = 0;
  721                 atomic_clearbits_int(&pr->ps_flags, PS_TRACED);
  722                 process_reparent(pr, tr);
  723                 prsignal(tr, SIGCHLD);
  724                 wakeup(tr);
  725         } else {
  726                 scheduler_wait_hook(waiter, p);
  727                 rup = &waiter->p_p->ps_cru;
  728                 ruadd(rup, pr->ps_ru);
  729                 LIST_REMOVE(pr, ps_list);       /* off zombprocess */
  730                 freepid(pr->ps_pid);
  731                 process_zap(pr);
  732         }
  733 }
  734 
  735 /*
  736  * give process back to original parent or init(8)
  737  */
  738 void
  739 process_untrace(struct process *pr)
  740 {
  741         struct process *ppr = NULL;
  742 
  743         KASSERT(pr->ps_flags & PS_TRACED);
  744 
  745         if (pr->ps_oppid != 0 &&
  746             (pr->ps_oppid != pr->ps_pptr->ps_pid))
  747                 ppr = prfind(pr->ps_oppid);
  748 
  749         /* not being traced any more */
  750         pr->ps_oppid = 0;
  751         atomic_clearbits_int(&pr->ps_flags, PS_TRACED);
  752         process_reparent(pr, ppr ? ppr : initprocess);
  753 }
  754 
  755 void
  756 process_clear_orphan(struct process *pr)
  757 {
  758         if (pr->ps_flags & PS_ORPHAN) {
  759                 LIST_REMOVE(pr, ps_orphan);
  760                 atomic_clearbits_int(&pr->ps_flags, PS_ORPHAN);
  761         }
  762 }
  763 
  764 /*
  765  * make process 'parent' the new parent of process 'child'.
  766  */
  767 void
  768 process_reparent(struct process *child, struct process *parent)
  769 {
  770 
  771         if (child->ps_pptr == parent)
  772                 return;
  773 
  774         KASSERT(child->ps_oppid == 0 ||
  775                 child->ps_oppid == child->ps_pptr->ps_pid);
  776 
  777         LIST_REMOVE(child, ps_sibling);
  778         LIST_INSERT_HEAD(&parent->ps_children, child, ps_sibling);
  779 
  780         process_clear_orphan(child);
  781         if (child->ps_flags & PS_TRACED) {
  782                 atomic_setbits_int(&child->ps_flags, PS_ORPHAN);
  783                 LIST_INSERT_HEAD(&child->ps_pptr->ps_orphans, child, ps_orphan);
  784         }
  785 
  786         child->ps_pptr = parent;
  787         child->ps_ppid = parent->ps_pid;
  788 }
  789 
  790 void
  791 process_zap(struct process *pr)
  792 {
  793         struct vnode *otvp;
  794         struct proc *p = pr->ps_mainproc;
  795 
  796         /*
  797          * Finally finished with old proc entry.
  798          * Unlink it from its process group and free it.
  799          */
  800         leavepgrp(pr);
  801         LIST_REMOVE(pr, ps_sibling);
  802         process_clear_orphan(pr);
  803 
  804         /*
  805          * Decrement the count of procs running with this uid.
  806          */
  807         (void)chgproccnt(pr->ps_ucred->cr_ruid, -1);
  808 
  809         /*
  810          * Release reference to text vnode
  811          */
  812         otvp = pr->ps_textvp;
  813         pr->ps_textvp = NULL;
  814         if (otvp)
  815                 vrele(otvp);
  816 
  817         KASSERT(pr->ps_refcnt == 1);
  818         if (pr->ps_ptstat != NULL)
  819                 free(pr->ps_ptstat, M_SUBPROC, sizeof(*pr->ps_ptstat));
  820         pool_put(&rusage_pool, pr->ps_ru);
  821         KASSERT(TAILQ_EMPTY(&pr->ps_threads));
  822         sigactsfree(pr->ps_sigacts);
  823         lim_free(pr->ps_limit);
  824         crfree(pr->ps_ucred);
  825         pool_put(&process_pool, pr);
  826         nprocesses--;
  827 
  828         proc_free(p);
  829 }

Cache object: 1e94cd34e487005badb14148700b5b61


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.