Statistics
| Branch: | Revision:

root / prex-0.9.0 / usr / server / proc / proc_exit.c @ 03e9c04a

History | View | Annotate | Download (5.12 KB)

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
}