Annotation of prex-old/usr/server/proc/exit.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005-2006, 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 <prex/prex.h>
35: #include <server/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 saves
48: * the exit code for waiting process.
49: */
50: int
51: proc_exit(struct msg *msg)
52: {
53: int exit_code;
54: struct proc *child, *parent;
55: list_t head, n;
56:
57: if (curproc == NULL)
58: return EINVAL;
59:
60: exit_code = msg->data[0];
61: dprintf("exit proc=%x task=%x code=%x\n", curproc,
62: msg->hdr.task, exit_code);
63:
64: if (curproc->stat == SZOMB)
65: return EBUSY;
66:
67: curproc->stat = SZOMB;
68: curproc->exit_code = exit_code;
69:
70: /*
71: * Set the parent pid of all child processes to 1 (init).
72: */
73: head = &curproc->children;
74: for (n = list_first(head); n != head; n = list_next(n)) {
75: child = list_entry(n, struct proc, sibling);
76: child->parent = &initproc;
77: list_insert(&initproc.children, &child->sibling);
78: }
79: /*
80: * Resume parent process which is wating in vfork.
81: */
82: parent = curproc->parent;
83: if (parent != NULL && parent->wait_vfork) {
84: vfork_end(parent);
85:
86: /*
87: * The child task loses its stack data.
88: * So, it can not run anymore.
89: */
90: task_terminate(curproc->task);
91: }
92:
93: /* Send a signal to the parent process. */
94: exception_raise(curproc->parent->task, SIGCHLD);
95: return 0;
96: }
97:
98: /*
99: * Stop process.
100: *
101: * This is similar with exit(), but it does not update the parent
102: * pid of any child processes.
103: */
104: int
105: proc_stop(struct msg *msg)
106: {
107: int code;
108:
109: if (curproc == NULL)
110: return EINVAL;
111:
112: code = msg->data[0];
113: dprintf("stop task=%x code=%x\n", msg->hdr.task, code);
114:
115: if (curproc->stat == SZOMB)
116: return EBUSY;
117:
118: curproc->stat = SSTOP;
119: curproc->exit_code = code;
120:
121: /* Send a signal to the parent process. */
122: exception_raise(curproc->parent->task, SIGCHLD);
123: return 0;
124: }
125:
126: /*
127: * Find the zombie process in the child processes. It just returns
128: * the pid and exit code if it find at least one zombie process.
129: *
130: * The library stub for waitpid() will wait the SIGCHLD signal in
131: * the stub code if there is no zombie process in child process.
132: * This signal is sent by proc_exit() or proc_stop() routines in
133: * the process server.
134: */
135: int
136: proc_waitpid(struct msg *msg)
137: {
138: pid_t pid, pid_child;
139: int options, code;
140: struct proc *p;
141: list_t head, n;
142:
143: if (curproc == NULL)
144: return EINVAL;
145:
146: pid = (pid_t)msg->data[0];
147: options = msg->data[1];
148: dprintf("wait task=%x pid=%x options=%x\n",
149: msg->hdr.task, pid, options);
150:
151: if (list_empty(&curproc->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->children;
163: for (n = list_first(head); n != head; n = list_next(n)) {
164: p = list_entry(n, struct proc, sibling);
165:
166: /*
167: * Check if pid matches.
168: */
169: if (pid > 0) {
170: if (p->pid != pid)
171: continue;
172: } else if (pid == 0) {
173: if (p->pgrp->pgid != curproc->pgrp->pgid)
174: continue;
175: } else if (pid != -1) {
176: if (p->pgrp->pgid != -pid)
177: continue;
178: }
179: /*
180: * Get the exit code.
181: */
182: if (p->stat == SSTOP) {
183: pid_child = p->pid;
184: code = p->exit_code;
185: break;
186: } else if (p->stat == SZOMB) {
187: pid_child = p->pid;
188: code = p->exit_code;
189: proc_cleanup(p);
190: break;
191: }
192: }
193: msg->data[0] = pid_child;
194: msg->data[1] = code;
195: return 0;
196: }
CVSweb