Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/proc/proc_exit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_exit
  2. stop
  3. sys_waitpid

   1 /*
   2  * Copyright (c) 2005-2008, Kohsuke Ohtani
   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. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * exit.c - process exit and wait
  32  */
  33 
  34 #include <sys/prex.h>
  35 #include <ipc/proc.h>
  36 #include <sys/list.h>
  37 
  38 #include <unistd.h>
  39 #include <errno.h>
  40 #include <signal.h>
  41 
  42 #include "proc.h"
  43 
  44 /*
  45  * Exit process.
  46  *
  47  * process_exit() sets the process state to zombie state, and it
  48  * saves the exit code for waiting process.
  49  */
  50 int
  51 sys_exit(int exitcode)
  52 {
  53         struct proc *child, *parent;
  54         list_t head, n;
  55         int error;
  56 
  57         DPRINTF(("proc: exit pid=%d code=%x\n", curproc->p_pid, exitcode));
  58 
  59         if (curproc->p_stat == SZOMB)
  60                 return EBUSY;
  61 
  62         /*
  63          * Enter zombie state.
  64          */
  65         curproc->p_stat = SZOMB;
  66         curproc->p_exitcode = exitcode;
  67         p_remove(curproc);
  68 
  69         /*
  70          * Set the parent pid of all child processes to 1 (init).
  71          */
  72         head = &curproc->p_children;
  73         n = list_first(head);
  74         while (n != head) {
  75                 child = list_entry(n, struct proc, p_sibling);
  76                 n = list_next(n);
  77 
  78                 child->p_parent = &initproc;
  79                 list_remove(&child->p_sibling);
  80                 list_insert(&initproc.p_children, &child->p_sibling);
  81         }
  82 
  83         /*
  84          * Resume parent process which is wating in vfork.
  85          */
  86         parent = curproc->p_parent;
  87         if (parent != NULL && parent->p_vforked) {
  88                 vfork_end(parent);
  89 
  90                 /*
  91                  * The child task loses its stack data.
  92                  * So, it can not run anymore.
  93                  */
  94                 error = task_terminate(curproc->p_task);
  95                 if (error)
  96                         sys_panic("proc: can not terminate a task for exit");
  97         }
  98 
  99         /* Send a signal to the parent process. */
 100         DPRINTF(("proc: exit send SIGCHLD to pid=%d\n",
 101                  curproc->p_parent->p_pid));
 102         exception_raise(curproc->p_parent->p_task, SIGCHLD);
 103 
 104         return 0;
 105 }
 106 
 107 /*
 108  * Stop process.
 109  *
 110  * This is similar with exit(), but it does not update the parent
 111  * pid of any child processes.
 112  */
 113 int
 114 stop(int exitcode)
 115 {
 116 
 117         DPRINTF(("proc: stop code=%x\n", exitcode));
 118 
 119         if (curproc->p_stat == SZOMB)
 120                 return EBUSY;
 121 
 122         curproc->p_stat = SSTOP;
 123         curproc->p_exitcode = exitcode;
 124 
 125         /* Send a signal to the parent process. */
 126         exception_raise(curproc->p_parent->p_task, SIGCHLD);
 127 
 128         return 0;
 129 }
 130 
 131 /*
 132  * Find the zombie process in the child processes. It just
 133  * returns the pid and exit code if it find at least one zombie
 134  * process.
 135  *
 136  * The library stub for waitpid() will wait the SIGCHLD signal in
 137  * the stub code if there is no zombie process in child process.
 138  * This signal is sent by proc_exit() or proc_stop() routines in
 139  * the process server.
 140  */
 141 int
 142 sys_waitpid(pid_t pid, int *status, int options, pid_t *retval)
 143 {
 144         pid_t pid_child;
 145         int code, match;
 146         struct proc *p;
 147         list_t head, n;
 148 
 149         DPRINTF(("proc: wait pid=%d options=%x\n", pid, options));
 150 
 151         if (list_empty(&curproc->p_children))
 152                 return ECHILD;  /* No child process */
 153 
 154         /* Set the default pid and exit code */
 155         pid_child = 0;
 156         code = 0;
 157 
 158         /*
 159          * Check all processes.
 160          */
 161         p = NULL;
 162         head = &curproc->p_children;
 163         for (n = list_first(head); n != head; n = list_next(n)) {
 164                 p = list_entry(n, struct proc, p_sibling);
 165 
 166                 /*
 167                  * Check if pid matches.
 168                  */
 169                 match = 0;
 170                 if (pid > 0) {
 171                         /*
 172                          * Wait a specific child process.
 173                          */
 174                         if (p->p_pid == pid)
 175                                 match = 1;
 176                 } else if (pid == 0) {
 177                         /*
 178                          * Wait a process who has same pgid.
 179                          */
 180                         if (p->p_pgrp->pg_pgid == curproc->p_pgrp->pg_pgid)
 181                                 match = 1;
 182                 } else if (pid != -1) {
 183                         /*
 184                          * Wait a specific pgid.
 185                          */
 186                         if (p->p_pgrp->pg_pgid == -pid)
 187                                 match = 1;
 188                 } else {
 189                         /*
 190                          * pid = -1 means wait any child process.
 191                          */
 192                         match = 1;
 193                 }
 194                 if (match) {
 195                         /*
 196                          * Get the exit code.
 197                          */
 198                         if (p->p_stat == SSTOP) {
 199                                 pid_child = p->p_pid;
 200                                 code = p->p_exitcode;
 201                                 break;
 202                         } else if (p->p_stat == SZOMB) {
 203                                 pid_child = p->p_pid;
 204                                 code = p->p_exitcode;
 205                                 cleanup(p);
 206                                 break;
 207                         }
 208                 }
 209         }
 210         *status = code;
 211         *retval = pid_child;
 212         return 0;
 213 }

/* [<][>][^][v][top][bottom][index][help] */