home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_exit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  10.0 KB  |  404 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_exit.c    7.35 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "map.h"
  39. #include "ioctl.h"
  40. #include "tty.h"
  41. #include "time.h"
  42. #include "resource.h"
  43. #include "kernel.h"
  44. #include "proc.h"
  45. #include "buf.h"
  46. #include "wait.h"
  47. #include "file.h"
  48. #include "vnode.h"
  49. #include "syslog.h"
  50. #include "malloc.h"
  51. #include "resourcevar.h"
  52.  
  53. #include "machine/cpu.h"
  54. #ifdef COMPAT_43
  55. #include "machine/reg.h"
  56. #include "machine/psl.h"
  57. #endif
  58.  
  59. #include "vm/vm.h"
  60. #include "vm/vm_kern.h"
  61.  
  62. /*
  63.  * Exit system call: pass back caller's arg
  64.  */
  65. /* ARGSUSED */
  66. rexit(p, uap, retval)
  67.     struct proc *p;
  68.     struct args {
  69.         int    rval;
  70.     } *uap;
  71.     int *retval;
  72. {
  73.  
  74.     exit(p, W_EXITCODE(uap->rval, 0));
  75.     /* NOTREACHED */
  76. }
  77.  
  78. /*
  79.  * Exit: deallocate address space and other resources,
  80.  * change proc state to zombie, and unlink proc from allproc
  81.  * and parent's lists.  Save exit status and rusage for wait().
  82.  * Check for child processes and orphan them.
  83.  */
  84. exit(p, rv)
  85.     register struct proc *p;
  86.     int rv;
  87. {
  88.     register struct proc *q, *nq;
  89.     register struct proc **pp;
  90.     int s;
  91.  
  92. #ifdef PGINPROF
  93.     vmsizmon();
  94. #endif
  95.     MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
  96.         M_ZOMBIE, M_WAITOK);
  97.     /*
  98.      * If parent is waiting for us to exit or exec,
  99.      * SPPWAIT is set; we will wakeup the parent below.
  100.      */
  101.     p->p_flag &= ~(STRC|SPPWAIT);
  102.     p->p_flag |= SWEXIT;
  103.     p->p_sigignore = ~0;
  104.     p->p_sig = 0;
  105.     untimeout(realitexpire, (caddr_t)p);
  106.  
  107.     /*
  108.      * Close open files and release open-file table.
  109.      * This may block!
  110.      */
  111.     fdfree(p);
  112.  
  113.     /* The next two chunks should probably be moved to vmspace_exit. */
  114. #ifdef SYSVSHM
  115.     if (p->p_vmspace->vm_shm)
  116.         shmexit(p);
  117. #endif
  118.     /*
  119.      * Release user portion of address space.
  120.      * This releases references to vnodes,
  121.      * which could cause I/O if the file has been unlinked.
  122.      * Need to do this early enough that we can still sleep.
  123.      * Can't free the entire vmspace as the kernel stack
  124.      * may be mapped within that space also.
  125.      */
  126.     if (p->p_vmspace->vm_refcnt == 1)
  127.         (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS,
  128.             VM_MAXUSER_ADDRESS);
  129.  
  130.     if (p->p_pid == 1)
  131.         panic("init died");
  132.     if (SESS_LEADER(p)) {
  133.         register struct session *sp = p->p_session;
  134.  
  135.         if (sp->s_ttyvp) {
  136.             /*
  137.              * Controlling process.
  138.              * Signal foreground pgrp,
  139.              * drain controlling terminal
  140.              * and revoke access to controlling terminal.
  141.              */
  142.             if (sp->s_ttyp->t_session == sp) {
  143.                 if (sp->s_ttyp->t_pgrp)
  144.                     pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
  145.                 (void) ttywait(sp->s_ttyp);
  146.                 vgoneall(sp->s_ttyvp);
  147.             }
  148.             vrele(sp->s_ttyvp);
  149.             sp->s_ttyvp = NULL;
  150.             /*
  151.              * s_ttyp is not zero'd; we use this to indicate
  152.              * that the session once had a controlling terminal.
  153.              * (for logging and informational purposes)
  154.              */
  155.         }
  156.         sp->s_leader = NULL;
  157.     }
  158.     fixjobc(p, p->p_pgrp, 0);
  159.     p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
  160.     (void) acct(p);
  161.     if (--p->p_limit->p_refcnt == 0)
  162.         FREE(p->p_limit, M_SUBPROC);
  163. #ifdef KTRACE
  164.     /* 
  165.      * release trace file
  166.      */
  167.     if (p->p_tracep)
  168.         vrele(p->p_tracep);
  169. #endif
  170.  
  171.     /*
  172.      * Remove proc from allproc queue and pidhash chain.
  173.      * Place onto zombproc.  Unlink from parent's child list.
  174.      */
  175.     if (*p->p_prev = p->p_nxt)
  176.         p->p_nxt->p_prev = p->p_prev;
  177.     if (p->p_nxt = zombproc)
  178.         p->p_nxt->p_prev = &p->p_nxt;
  179.     p->p_prev = &zombproc;
  180.     zombproc = p;
  181.     p->p_stat = SZOMB;
  182.     curproc = NULL;
  183.     for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
  184.         if (*pp == p) {
  185.             *pp = p->p_hash;
  186.             goto done;
  187.         }
  188.     panic("exit");
  189. done:
  190.  
  191.     if (p->p_cptr)        /* only need this if any child is S_ZOMB */
  192.         wakeup((caddr_t) initproc);
  193.     for (q = p->p_cptr; q != NULL; q = nq) {
  194.         nq = q->p_osptr;
  195.         if (nq != NULL)
  196.             nq->p_ysptr = NULL;
  197.         if (initproc->p_cptr)
  198.             initproc->p_cptr->p_ysptr = q;
  199.         q->p_osptr = initproc->p_cptr;
  200.         q->p_ysptr = NULL;
  201.         initproc->p_cptr = q;
  202.  
  203.         q->p_pptr = initproc;
  204.         /*
  205.          * Traced processes are killed
  206.          * since their existence means someone is screwing up.
  207.          */
  208.         if (q->p_flag&STRC) {
  209.             q->p_flag &= ~STRC;
  210.             psignal(q, SIGKILL);
  211.         }
  212.     }
  213.     p->p_cptr = NULL;
  214.  
  215.     /*
  216.      * Save exit status and final rusage info,
  217.      * adding in child rusage info and self times.
  218.      */
  219.     p->p_xstat = rv;
  220.     *p->p_ru = p->p_stats->p_ru;
  221.     p->p_ru->ru_stime = p->p_stime;
  222.     p->p_ru->ru_utime = p->p_utime;
  223.     ruadd(p->p_ru, &p->p_stats->p_cru);
  224.  
  225.     /*
  226.      * Notify parent that we're gone.
  227.      */
  228.     psignal(p->p_pptr, SIGCHLD);
  229.     wakeup((caddr_t)p->p_pptr);
  230. #if defined(tahoe)
  231.     /* move this to cpu_exit */
  232.     p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
  233. #endif
  234.     /*
  235.      * Finally, call machine-dependent code to release the remaining
  236.      * resources including address space, the kernel stack and pcb.
  237.      * The address space is released by "vmspace_free(p->p_vmspace)";
  238.      * This is machine-dependent, as we may have to change stacks
  239.      * or ensure that the current one isn't reallocated before we
  240.      * finish.  cpu_exit will end with a call to swtch(), finishing
  241.      * our execution (pun intended).
  242.      */
  243.     cpu_exit(p);
  244.     /* NOTREACHED */
  245. }
  246.  
  247. #ifdef COMPAT_43
  248. owait(p, uap, retval)
  249.     struct proc *p;
  250.     register struct args {
  251.         int    pid;
  252.         int    *status;
  253.         int    options;
  254.         struct    rusage *rusage;
  255.         int    compat;
  256.     } *uap;
  257.     int *retval;
  258. {
  259.  
  260.     if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) {
  261.         uap->options = 0;
  262.         uap->rusage = 0;
  263.     } else {
  264.         uap->options = p->p_regs[R0];
  265.         uap->rusage = (struct rusage *)p->p_regs[R1];
  266.     }
  267.     uap->pid = WAIT_ANY;
  268.     uap->status = 0;
  269.     uap->compat = 1;
  270.     return (wait1(p, uap, retval));
  271. }
  272.  
  273. wait4(p, uap, retval)
  274.     struct proc *p;
  275.     struct args {
  276.         int    pid;
  277.         int    *status;
  278.         int    options;
  279.         struct    rusage *rusage;
  280.         int    compat;
  281.     } *uap;
  282.     int *retval;
  283. {
  284.  
  285.     uap->compat = 0;
  286.     return (wait1(p, uap, retval));
  287. }
  288. #else
  289. #define    wait1    wait4
  290. #endif
  291.  
  292. /*
  293.  * Wait: check child processes to see if any have exited,
  294.  * stopped under trace, or (optionally) stopped by a signal.
  295.  * Pass back status and deallocate exited child's proc structure.
  296.  */
  297. wait1(q, uap, retval)
  298.     register struct proc *q;
  299.     register struct args {
  300.         int    pid;
  301.         int    *status;
  302.         int    options;
  303.         struct    rusage *rusage;
  304. #ifdef COMPAT_43
  305.         int compat;
  306. #endif
  307.     } *uap;
  308.     int retval[];
  309. {
  310.     register int nfound;
  311.     register struct proc *p;
  312.     int status, error;
  313.  
  314.     if (uap->pid == 0)
  315.         uap->pid = -q->p_pgid;
  316. #ifdef notyet
  317.     if (uap->options &~ (WUNTRACED|WNOHANG))
  318.         return (EINVAL);
  319. #endif
  320. loop:
  321.     nfound = 0;
  322.     for (p = q->p_cptr; p; p = p->p_osptr) {
  323.         if (uap->pid != WAIT_ANY &&
  324.             p->p_pid != uap->pid && p->p_pgid != -uap->pid)
  325.             continue;
  326.         nfound++;
  327.         if (p->p_stat == SZOMB) {
  328.             retval[0] = p->p_pid;
  329. #ifdef COMPAT_43
  330.             if (uap->compat)
  331.                 retval[1] = p->p_xstat;
  332.             else
  333. #endif
  334.             if (uap->status) {
  335.                 status = p->p_xstat;    /* convert to int */
  336.                 if (error = copyout((caddr_t)&status,
  337.                     (caddr_t)uap->status, sizeof(status)))
  338.                     return (error);
  339.             }
  340.             if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
  341.                 (caddr_t)uap->rusage, sizeof (struct rusage))))
  342.                 return (error);
  343.             p->p_xstat = 0;
  344.             ruadd(&q->p_stats->p_cru, p->p_ru);
  345.             FREE(p->p_ru, M_ZOMBIE);
  346.             if (--p->p_cred->p_refcnt == 0) {
  347.                 crfree(p->p_cred->pc_ucred);
  348.                 FREE(p->p_cred, M_SUBPROC);
  349.             }
  350.  
  351.             /*
  352.              * Finally finished with old proc entry.
  353.              * Unlink it from its process group and free it.
  354.              */
  355.             leavepgrp(p);
  356.             if (*p->p_prev = p->p_nxt)    /* off zombproc */
  357.                 p->p_nxt->p_prev = p->p_prev;
  358.             if (q = p->p_ysptr)
  359.                 q->p_osptr = p->p_osptr;
  360.             if (q = p->p_osptr)
  361.                 q->p_ysptr = p->p_ysptr;
  362.             if ((q = p->p_pptr)->p_cptr == p)
  363.                 q->p_cptr = p->p_osptr;
  364.  
  365.             /*
  366.              * Give machine-dependent layer a chance
  367.              * to free anything that cpu_exit couldn't
  368.              * release while still running in process context.
  369.              */
  370.             cpu_wait(p);
  371.             FREE(p, M_PROC);
  372.             nprocs--;
  373.             return (0);
  374.         }
  375.         if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
  376.             (p->p_flag & STRC || uap->options & WUNTRACED)) {
  377.             p->p_flag |= SWTED;
  378.             retval[0] = p->p_pid;
  379. #ifdef COMPAT_43
  380.             if (uap->compat) {
  381.                 retval[1] = W_STOPCODE(p->p_xstat);
  382.                 error = 0;
  383.             } else
  384. #endif
  385.             if (uap->status) {
  386.                 status = W_STOPCODE(p->p_xstat);
  387.                 error = copyout((caddr_t)&status,
  388.                     (caddr_t)uap->status, sizeof(status));
  389.             } else
  390.                 error = 0;
  391.             return (error);
  392.         }
  393.     }
  394.     if (nfound == 0)
  395.         return (ECHILD);
  396.     if (uap->options & WNOHANG) {
  397.         retval[0] = 0;
  398.         return (0);
  399.     }
  400.     if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
  401.         return (error);
  402.     goto loop;
  403. }
  404.