]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_exit.c
xnu-344.34.tar.gz
[apple/xnu.git] / bsd / kern / kern_exit.c
CommitLineData
1c79356b 1/*
9bccf70c 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
de355530
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
61 */
62
63#include <machine/reg.h>
64#include <machine/psl.h>
65
66#include "compat_43.h"
67
68#include <sys/param.h>
69#include <sys/systm.h>
70#include <sys/ioctl.h>
71#include <sys/proc.h>
72#include <sys/tty.h>
73#include <sys/time.h>
74#include <sys/resource.h>
75#include <sys/kernel.h>
76#include <sys/buf.h>
77#include <sys/wait.h>
78#include <sys/file.h>
79#include <sys/vnode.h>
80#include <sys/syslog.h>
81#include <sys/malloc.h>
82#include <sys/resourcevar.h>
83#include <sys/ptrace.h>
84#include <sys/user.h>
85
86#include <mach/mach_types.h>
87#include <kern/thread.h>
88#include <kern/thread_act.h>
9bccf70c 89#include <kern/sched_prim.h>
1c79356b 90#include <kern/assert.h>
9bccf70c
A
91#if KTRACE
92#include <sys/ktrace.h>
93#endif
1c79356b
A
94
95extern char init_task_failure_data[];
0b4e3aa0 96int exit1 __P((struct proc *, int, int *));
1c79356b
A
97
98/*
99 * exit --
100 * Death of process.
101 */
102struct exit_args {
103 int rval;
104};
105void
106exit(p, uap, retval)
107 struct proc *p;
108 struct exit_args *uap;
109 int *retval;
110{
0b4e3aa0 111 exit1(p, W_EXITCODE(uap->rval, 0), retval);
1c79356b 112
9bccf70c 113 /* drop funnel before we return */
1c79356b
A
114 thread_funnel_set(kernel_flock, FALSE);
115 thread_exception_return();
116 /* NOTREACHED */
117 while (TRUE)
9bccf70c 118 thread_block(THREAD_CONTINUE_NULL);
1c79356b
A
119 /* NOTREACHED */
120}
121
122/*
123 * Exit: deallocate address space and other resources, change proc state
124 * to zombie, and unlink proc from allproc and parent's lists. Save exit
125 * status and rusage for wait(). Check for child processes and orphan them.
126 */
0b4e3aa0
A
127int
128exit1(p, rv, retval)
1c79356b
A
129 register struct proc *p;
130 int rv;
0b4e3aa0 131 int * retval;
1c79356b
A
132{
133 register struct proc *q, *nq;
134 thread_t self = current_thread();
135 thread_act_t th_act_self = current_act();
136 struct task *task = p->task;
137 register int i,s;
138 struct uthread *ut;
139
140 /*
141 * If a thread in this task has already
142 * called exit(), then halt any others
143 * right here.
144 */
0b4e3aa0
A
145
146 ut = get_bsdthread_info(th_act_self);
147 if (ut->uu_flag & P_VFORK) {
9bccf70c 148 (void)vfork_exit(p, rv);
0b4e3aa0
A
149 vfork_return(th_act_self, p->p_pptr, p , retval);
150 unix_syscall_return(0);
151 /* NOT REACHED */
152 }
1c79356b
A
153 signal_lock(p);
154 while (p->exit_thread != self) {
155 if (sig_try_locked(p) <= 0) {
156 if (get_threadtask(th_act_self) != task) {
157 signal_unlock(p);
0b4e3aa0 158 return(0);
1c79356b
A
159 }
160 signal_unlock(p);
161 thread_terminate(th_act_self);
162 thread_funnel_set(kernel_flock, FALSE);
163 thread_exception_return();
164 /* NOTREACHED */
165 }
166 sig_lock_to_exit(p);
167 }
168 signal_unlock(p);
169 if (p->p_pid == 1) {
170 printf("pid 1 exited (signal %d, exit %d)",
171 WTERMSIG(rv), WEXITSTATUS(rv));
172 panic("init died\nState at Last Exception:\n\n%s",
173 init_task_failure_data);
174 }
175
176 s = splsched();
177 p->p_flag |= P_WEXIT;
178 splx(s);
9bccf70c 179 (void)proc_prepareexit(p);
1c79356b
A
180 p->p_xstat = rv;
181
182 /* task terminate will call proc_terminate and that cleans it up */
183 task_terminate_internal(task);
184
185 /*
186 * we come back and returns to AST which
187 * should cleanup the rest
188 */
189#if 0
190 if (task == current_task()) {
191 thread_exception_return();
192 /*NOTREACHED*/
193 }
194
195 while (task == current_task()) {
196 thread_terminate_self();
197 /*NOTREACHED*/
198 }
199#endif
0b4e3aa0 200 return(0);
1c79356b
A
201}
202
203void
204proc_prepareexit(struct proc *p)
205{
206 int s;
207 struct uthread *ut;
208 thread_t self = current_thread();
209 thread_act_t th_act_self = current_act();
210
1c79356b
A
211 /*
212 * Remove proc from allproc queue and from pidhash chain.
213 * Need to do this before we do anything that can block.
214 * Not doing causes things like mount() find this on allproc
215 * in partially cleaned state.
216 */
217 LIST_REMOVE(p, p_list);
218 LIST_REMOVE(p, p_hash);
219
220#ifdef PGINPROF
221 vmsizmon();
222#endif
223 /*
224 * If parent is waiting for us to exit or exec,
225 * P_PPWAIT is set; we will wakeup the parent below.
226 */
227 p->p_flag &= ~(P_TRACED | P_PPWAIT);
228 p->p_sigignore = ~0;
229 p->p_siglist = 0;
230 ut = get_bsdthread_info(th_act_self);
9bccf70c
A
231 ut->uu_siglist = 0;
232 untimeout(realitexpire, (caddr_t)p->p_pid);
1c79356b
A
233}
234
235void
236proc_exit(struct proc *p)
237{
9bccf70c 238 register struct proc *q, *nq, *pp;
1c79356b
A
239 thread_t self = current_thread();
240 thread_act_t th_act_self = current_act();
241 struct task *task = p->task;
242 register int i,s;
1c79356b
A
243 boolean_t funnel_state;
244
245 /* This can happen if thread_terminate of the single thread
246 * process
247 */
248
249 funnel_state = thread_funnel_set(kernel_flock, TRUE);
250 if( !(p->p_flag & P_WEXIT)) {
251 s = splsched();
252 p->p_flag |= P_WEXIT;
253 splx(s);
254 proc_prepareexit(p);
255 }
256
257 MALLOC_ZONE(p->p_ru, struct rusage *,
258 sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
259
260 /*
261 * Close open files and release open-file table.
262 * This may block!
263 */
264 fdfree(p);
265
266 /* Close ref SYSV Shared memory*/
267 if (p->vm_shm)
268 shmexit(p);
9bccf70c
A
269 /* Release SYSV semaphores */
270 semexit(p);
1c79356b
A
271
272 if (SESS_LEADER(p)) {
273 register struct session *sp = p->p_session;
274
275 if (sp->s_ttyvp) {
fa4905b1
A
276 struct vnode *ttyvp;
277
1c79356b
A
278 /*
279 * Controlling process.
280 * Signal foreground pgrp,
281 * drain controlling terminal
282 * and revoke access to controlling terminal.
283 */
284 if (sp->s_ttyp->t_session == sp) {
285 if (sp->s_ttyp->t_pgrp)
286 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
287 (void) ttywait(sp->s_ttyp);
288 /*
289 * The tty could have been revoked
290 * if we blocked.
291 */
292 if (sp->s_ttyvp)
293 VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
294 }
fa4905b1 295 ttyvp = sp->s_ttyvp;
1c79356b 296 sp->s_ttyvp = NULL;
fa4905b1
A
297 if (ttyvp)
298 vrele(ttyvp);
1c79356b
A
299 /*
300 * s_ttyp is not zero'd; we use this to indicate
301 * that the session once had a controlling terminal.
302 * (for logging and informational purposes)
303 */
304 }
305 sp->s_leader = NULL;
306 }
307
308 fixjobc(p, p->p_pgrp, 0);
309 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
9bccf70c
A
310 (void)acct_process(p);
311
1c79356b
A
312#if KTRACE
313 /*
314 * release trace file
315 */
316 p->p_traceflag = 0; /* don't trace the vrele() */
fa4905b1
A
317 if (p->p_tracep) {
318 struct vnode *tvp = p->p_tracep;
319 p->p_tracep = NULL;
320 vrele(tvp);
321 }
1c79356b
A
322#endif
323
1c79356b
A
324 q = p->p_children.lh_first;
325 if (q) /* only need this if any child is S_ZOMB */
326 wakeup((caddr_t) initproc);
327 for (; q != 0; q = nq) {
328 nq = q->p_sibling.le_next;
329 proc_reparent(q, initproc);
330 /*
331 * Traced processes are killed
332 * since their existence means someone is messing up.
333 */
334 if (q->p_flag & P_TRACED) {
335 q->p_flag &= ~P_TRACED;
336 if (q->sigwait_thread) {
9bccf70c
A
337 thread_t sig_shuttle;
338
339 sig_shuttle = (thread_t)getshuttle_thread((thread_act_t)q->sigwait_thread);
1c79356b
A
340 /*
341 * The sigwait_thread could be stopped at a
342 * breakpoint. Wake it up to kill.
343 * Need to do this as it could be a thread which is not
344 * the first thread in the task. So any attempts to kill
345 * the process would result into a deadlock on q->sigwait.
346 */
9bccf70c 347 thread_resume((thread_act_t)q->sigwait_thread);
1c79356b 348 clear_wait(sig_shuttle, THREAD_INTERRUPTED);
9bccf70c 349 threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0);
1c79356b
A
350 }
351 psignal(q, SIGKILL);
352 }
353 }
354
1c79356b
A
355 /*
356 * Save exit status and final rusage info, adding in child rusage
357 * info and self times.
358 */
359 *p->p_ru = p->p_stats->p_ru;
360
361 timerclear(&p->p_ru->ru_utime);
362 timerclear(&p->p_ru->ru_stime);
363
364 if (task) {
365 task_basic_info_data_t tinfo;
366 task_thread_times_info_data_t ttimesinfo;
367 int task_info_stuff, task_ttimes_stuff;
368 struct timeval ut,st;
369
370 task_info_stuff = TASK_BASIC_INFO_COUNT;
371 task_info(task, TASK_BASIC_INFO,
372 &tinfo, &task_info_stuff);
373 p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds;
374 p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds;
375 p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds;
376 p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds;
377
378 task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT;
379 task_info(task, TASK_THREAD_TIMES_INFO,
380 &ttimesinfo, &task_ttimes_stuff);
381
382 ut.tv_sec = ttimesinfo.user_time.seconds;
383 ut.tv_usec = ttimesinfo.user_time.microseconds;
384 st.tv_sec = ttimesinfo.system_time.seconds;
385 st.tv_usec = ttimesinfo.system_time.microseconds;
386 timeradd(&ut,&p->p_ru->ru_utime,&p->p_ru->ru_utime);
387 timeradd(&st,&p->p_ru->ru_stime,&p->p_ru->ru_stime);
388 }
389
1c79356b
A
390 ruadd(p->p_ru, &p->p_stats->p_cru);
391
392 /*
393 * Free up profiling buffers.
394 */
395 {
396 struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn;
397
398 p1 = p0->pr_next;
399 p0->pr_next = NULL;
400 p0->pr_scale = 0;
401
402 for (; p1 != NULL; p1 = pn) {
403 pn = p1->pr_next;
404 kfree((vm_offset_t)p1, sizeof *p1);
405 }
406 }
407
408 /*
409 * Other substructures are freed from wait().
410 */
411 FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC);
412 p->p_stats = NULL;
413
414 FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC);
415 p->p_sigacts = NULL;
416
417 if (--p->p_limit->p_refcnt == 0)
418 FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
419 p->p_limit = NULL;
420
421 /*
422 * Finish up by terminating the task
423 * and halt this thread (only if a
424 * member of the task exiting).
425 */
426 p->task = TASK_NULL;
427 //task->proc = NULL;
428 set_bsdtask_info(task, NULL);
429
430 /*
431 * Notify parent that we're gone.
432 */
9bccf70c
A
433 if (p->p_pptr->p_flag & P_NOCLDWAIT) {
434 struct proc * pp = p->p_pptr;
435
436 proc_reparent(p, initproc);
437 /* If there are no more children wakeup parent */
438 if (LIST_EMPTY(&pp->p_children))
439 wakeup((caddr_t)pp);
440 }
441 /* should be fine as parent proc would be initproc */
442 pp = p->p_pptr;
443 if (pp != initproc) {
444 pp->si_pid = p->p_pid;
445 pp->si_status = p->p_xstat;
446 pp->si_code = CLD_EXITED;
447 pp->si_uid = p->p_cred->p_ruid;
448 }
449 psignal(pp, SIGCHLD);
450
1c79356b
A
451
452 /* Place onto zombproc. */
453 LIST_INSERT_HEAD(&zombproc, p, p_list);
454 p->p_stat = SZOMB;
455
456 /* and now wakeup the parent */
457 wakeup((caddr_t)p->p_pptr);
458
459 (void) thread_funnel_set(kernel_flock, funnel_state);
460}
461
462
463struct wait4_args {
464 int pid;
465 int *status;
466 int options;
467 struct rusage *rusage;
468};
469
470#if COMPAT_43
471int
472owait(p, uap, retval)
473 struct proc *p;
474 void *uap;
475 int *retval;
476{
477 struct wait4_args *a;
478
479 a = (struct wait4_args *)get_bsduthreadarg(current_act());
480
481 a->options = 0;
482 a->rusage = NULL;
483 a->pid = WAIT_ANY;
484 a->status = NULL;
485 return (wait1(p, a, retval, 1));
486}
487
488int
489wait4(p, uap, retval)
490 struct proc *p;
491 struct wait4_args *uap;
492 int *retval;
493{
1c79356b
A
494 return (wait1(p, uap, retval, 0));
495}
496
497struct owait3_args {
498 int *status;
499 int options;
500 struct rusage *rusage;
501};
502
503int
504owait3(p, uap, retval)
505 struct proc *p;
506 struct owait3_args *uap;
507 int *retval;
508{
509 struct wait4_args *a;
510
511 a = (struct wait4_args *)get_bsduthreadarg(current_act);
512
513 a->rusage = uap->rusage;
514 a->options = uap->options;
515 a->status = uap->status;
516 a->pid = WAIT_ANY;
517
518 return (wait1(p, a, retval, 1));
519}
520
521#else
522#define wait1 wait4
523#endif
524
525int
526wait1continue(result)
527{
7b1edb79
A
528 void *vt;
529 thread_act_t thread;
530 int *retval;
531 struct proc *p;
1c79356b 532
7b1edb79
A
533 if (result)
534 return(result);
1c79356b 535
7b1edb79
A
536 p = current_proc();
537 thread = current_act();
9bccf70c
A
538 vt = (void *)get_bsduthreadarg(thread);
539 retval = (int *)get_bsduthreadrval(thread);
1c79356b
A
540 wait1((struct proc *)p, (struct wait4_args *)vt, retval, 0);
541}
542
543int
544wait1(q, uap, retval, compat)
545 register struct proc *q;
546 register struct wait4_args *uap;
547 register_t *retval;
548#if COMPAT_43
549 int compat;
550#endif
551{
552 register int nfound;
553 register struct proc *p, *t;
554 int status, error;
fa4905b1 555 struct vnode *tvp;
1c79356b 556
7b1edb79 557retry:
1c79356b
A
558 if (uap->pid == 0)
559 uap->pid = -q->p_pgid;
560
561loop:
562 nfound = 0;
563 for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) {
564 if (uap->pid != WAIT_ANY &&
565 p->p_pid != uap->pid &&
566 p->p_pgid != -(uap->pid))
567 continue;
568 nfound++;
7b1edb79
A
569 if (p->p_flag & P_WAITING) {
570 (void)tsleep(&p->p_stat, PWAIT, "waitcoll", 0);
571 goto loop;
572 }
573 p->p_flag |= P_WAITING; /* only allow single thread to wait() */
574
1c79356b
A
575 if (p->p_stat == SZOMB) {
576 retval[0] = p->p_pid;
577#if COMPAT_43
578 if (compat)
579 retval[1] = p->p_xstat;
580 else
581#endif
582 if (uap->status) {
583 status = p->p_xstat; /* convert to int */
584 if (error = copyout((caddr_t)&status,
585 (caddr_t)uap->status,
586 sizeof(status))) {
7b1edb79
A
587 p->p_flag &= ~P_WAITING;
588 wakeup(&p->p_stat);
1c79356b
A
589 return (error);
590 }
591 }
592 if (uap->rusage &&
593 (error = copyout((caddr_t)p->p_ru,
594 (caddr_t)uap->rusage,
595 sizeof (struct rusage)))) {
7b1edb79
A
596 p->p_flag &= ~P_WAITING;
597 wakeup(&p->p_stat);
1c79356b
A
598 return (error);
599 }
600 /*
601 * If we got the child via a ptrace 'attach',
602 * we need to give it back to the old parent.
603 */
604 if (p->p_oppid && (t = pfind(p->p_oppid))) {
605 p->p_oppid = 0;
606 proc_reparent(p, t);
9bccf70c
A
607 if (t != initproc) {
608 t->si_pid = p->p_pid;
609 t->si_status = p->p_xstat;
610 t->si_code = CLD_CONTINUED;
611 t->si_uid = p->p_cred->p_ruid;
612 }
1c79356b
A
613 psignal(t, SIGCHLD);
614 wakeup((caddr_t)t);
7b1edb79
A
615 p->p_flag &= ~P_WAITING;
616 wakeup(&p->p_stat);
1c79356b
A
617 return (0);
618 }
619 p->p_xstat = 0;
620 if (p->p_ru) {
621 ruadd(&q->p_stats->p_cru, p->p_ru);
622 FREE_ZONE(p->p_ru, sizeof *p->p_ru, M_ZOMBIE);
623 p->p_ru = NULL;
624 } else {
625 printf("Warning : lost p_ru for %s\n", p->p_comm);
626 }
627
628 /*
629 * Decrement the count of procs running with this uid.
630 */
631 (void)chgproccnt(p->p_cred->p_ruid, -1);
632
633 /*
634 * Free up credentials.
635 */
636 if (--p->p_cred->p_refcnt == 0) {
637 struct ucred *ucr = p->p_ucred;
638 struct pcred *pcr;
639
640 if (ucr != NOCRED) {
641 p->p_ucred = NOCRED;
642 crfree(ucr);
643 }
644 pcr = p->p_cred;
645 p->p_cred = NULL;
646 FREE_ZONE(pcr, sizeof *pcr, M_SUBPROC);
647 }
648
649 /*
650 * Release reference to text vnode
651 */
fa4905b1
A
652 tvp = p->p_textvp;
653 p->p_textvp = NULL;
654 if (tvp)
655 vrele(tvp);
1c79356b
A
656
657 /*
658 * Finally finished with old proc entry.
659 * Unlink it from its process group and free it.
660 */
661 leavepgrp(p);
662 LIST_REMOVE(p, p_list); /* off zombproc */
663 LIST_REMOVE(p, p_sibling);
7b1edb79 664 p->p_flag &= ~P_WAITING;
1c79356b
A
665 FREE_ZONE(p, sizeof *p, M_PROC);
666 nprocs--;
7b1edb79 667 wakeup(&p->p_stat);
1c79356b
A
668 return (0);
669 }
670 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
671 (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
672 p->p_flag |= P_WAITED;
673 retval[0] = p->p_pid;
674#if COMPAT_43
675 if (compat) {
676 retval[1] = W_STOPCODE(p->p_xstat);
677 error = 0;
678 } else
679#endif
680 if (uap->status) {
681 status = W_STOPCODE(p->p_xstat);
682 error = copyout((caddr_t)&status,
683 (caddr_t)uap->status,
684 sizeof(status));
685 } else
686 error = 0;
7b1edb79
A
687 p->p_flag &= ~P_WAITING;
688 wakeup(&p->p_stat);
1c79356b
A
689 return (error);
690 }
7b1edb79
A
691 p->p_flag &= ~P_WAITING;
692 wakeup(&p->p_stat);
1c79356b 693 }
7b1edb79 694 if (nfound == 0)
1c79356b 695 return (ECHILD);
7b1edb79 696
1c79356b
A
697 if (uap->options & WNOHANG) {
698 retval[0] = 0;
1c79356b
A
699 return (0);
700 }
701
7b1edb79 702 if (error = tsleep0((caddr_t)q, PWAIT | PCATCH, "wait", 0, wait1continue))
1c79356b 703 return (error);
7b1edb79 704
1c79356b
A
705 goto loop;
706}
707
708/*
709 * make process 'parent' the new parent of process 'child'.
710 */
711void
712proc_reparent(child, parent)
713 register struct proc *child;
714 register struct proc *parent;
715{
716
717 if (child->p_pptr == parent)
718 return;
719
720 LIST_REMOVE(child, p_sibling);
721 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
722 child->p_pptr = parent;
723}
724
1c79356b
A
725/*
726 * Make the current process an "init" process, meaning
727 * that it doesn't have a parent, and that it won't be
728 * gunned down by kill(-1, 0).
729 */
7b1edb79
A
730kern_return_t
731init_process(void)
1c79356b
A
732{
733 register struct proc *p = current_proc();
734
735 if (suser(p->p_ucred, &p->p_acflag))
736 return(KERN_NO_ACCESS);
737
738 if (p->p_pid != 1 && p->p_pgid != p->p_pid)
739 enterpgrp(p, p->p_pid, 0);
740 p->p_flag |= P_SYSTEM;
741
742 /*
743 * Take us out of the sibling chain, and
744 * out of our parent's child chain.
745 */
746 LIST_REMOVE(p, p_sibling);
747 p->p_sibling.le_prev = NULL;
748 p->p_sibling.le_next = NULL;
749 p->p_pptr = kernproc;
750
751 return(KERN_SUCCESS);
752}
753
754void
755process_terminate_self(void)
756{
757 struct proc *p = current_proc();
758
759 if (p != NULL) {
0b4e3aa0 760 exit1(p, W_EXITCODE(0, SIGKILL), (int *)NULL);
1c79356b
A
761 /*NOTREACHED*/
762 }
763}
7b1edb79 764
0b4e3aa0
A
765/*
766 * Exit: deallocate address space and other resources, change proc state
767 * to zombie, and unlink proc from allproc and parent's lists. Save exit
768 * status and rusage for wait(). Check for child processes and orphan them.
769 */
770
771void
772vfork_exit(p, rv)
9bccf70c 773 struct proc *p;
0b4e3aa0
A
774 int rv;
775{
776 register struct proc *q, *nq;
777 thread_t self = current_thread();
778 thread_act_t th_act_self = current_act();
779 struct task *task = p->task;
780 register int i,s;
781 struct uthread *ut;
782
783 /*
784 * If a thread in this task has already
785 * called exit(), then halt any others
786 * right here.
787 */
788
789 ut = get_bsdthread_info(th_act_self);
790#ifdef FIXME
791 signal_lock(p);
792 while (p->exit_thread != self) {
793 if (sig_try_locked(p) <= 0) {
794 if (get_threadtask(th_act_self) != task) {
795 signal_unlock(p);
796 return;
797 }
798 signal_unlock(p);
799 thread_terminate(th_act_self);
800 thread_funnel_set(kernel_flock, FALSE);
801 thread_exception_return();
802 /* NOTREACHED */
803 }
804 sig_lock_to_exit(p);
805 }
806 signal_unlock(p);
807 if (p->p_pid == 1) {
808 printf("pid 1 exited (signal %d, exit %d)",
809 WTERMSIG(rv), WEXITSTATUS(rv));
810panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data);
811 }
812#endif /* FIXME */
813
814 s = splsched();
815 p->p_flag |= P_WEXIT;
816 splx(s);
817 /*
818 * Remove proc from allproc queue and from pidhash chain.
819 * Need to do this before we do anything that can block.
820 * Not doing causes things like mount() find this on allproc
821 * in partially cleaned state.
822 */
823 LIST_REMOVE(p, p_list);
824 LIST_REMOVE(p, p_hash);
825 /*
826 * If parent is waiting for us to exit or exec,
827 * P_PPWAIT is set; we will wakeup the parent below.
828 */
829 p->p_flag &= ~(P_TRACED | P_PPWAIT);
830 p->p_sigignore = ~0;
831 p->p_siglist = 0;
832
9bccf70c
A
833 ut->uu_siglist = 0;
834 untimeout(realitexpire, (caddr_t)p->p_pid);
0b4e3aa0
A
835
836 p->p_xstat = rv;
837
9bccf70c 838 (void)vproc_exit(p);
0b4e3aa0
A
839}
840
0b4e3aa0
A
841void
842vproc_exit(struct proc *p)
843{
9bccf70c 844 register struct proc *q, *nq, *pp;
0b4e3aa0
A
845 thread_t self = current_thread();
846 thread_act_t th_act_self = current_act();
847 struct task *task = p->task;
848 register int i,s;
0b4e3aa0
A
849 boolean_t funnel_state;
850
851 MALLOC_ZONE(p->p_ru, struct rusage *,
852 sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
853
854 /*
855 * Close open files and release open-file table.
856 * This may block!
857 */
858 fdfree(p);
859
0b4e3aa0
A
860 if (SESS_LEADER(p)) {
861 register struct session *sp = p->p_session;
862
863 if (sp->s_ttyvp) {
fa4905b1
A
864 struct vnode *ttyvp;
865
0b4e3aa0
A
866 /*
867 * Controlling process.
868 * Signal foreground pgrp,
869 * drain controlling terminal
870 * and revoke access to controlling terminal.
871 */
872 if (sp->s_ttyp->t_session == sp) {
873 if (sp->s_ttyp->t_pgrp)
874 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
875 (void) ttywait(sp->s_ttyp);
876 /*
877 * The tty could have been revoked
878 * if we blocked.
879 */
880 if (sp->s_ttyvp)
881 VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
882 }
fa4905b1 883 ttyvp = sp->s_ttyvp;
0b4e3aa0 884 sp->s_ttyvp = NULL;
fa4905b1
A
885 if (ttyvp)
886 vrele(ttyvp);
0b4e3aa0
A
887 /*
888 * s_ttyp is not zero'd; we use this to indicate
889 * that the session once had a controlling terminal.
890 * (for logging and informational purposes)
891 */
892 }
893 sp->s_leader = NULL;
894 }
895
896 fixjobc(p, p->p_pgrp, 0);
897 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
9bccf70c 898
0b4e3aa0
A
899#if KTRACE
900 /*
901 * release trace file
902 */
903 p->p_traceflag = 0; /* don't trace the vrele() */
fa4905b1
A
904 if (p->p_tracep) {
905 struct vnode *tvp = p->p_tracep;
906 p->p_tracep = NULL;
907 vrele(tvp);
908 }
0b4e3aa0
A
909#endif
910
0b4e3aa0
A
911 q = p->p_children.lh_first;
912 if (q) /* only need this if any child is S_ZOMB */
913 wakeup((caddr_t) initproc);
914 for (; q != 0; q = nq) {
915 nq = q->p_sibling.le_next;
916 proc_reparent(q, initproc);
917 /*
918 * Traced processes are killed
919 * since their existence means someone is messing up.
920 */
921 if (q->p_flag & P_TRACED) {
922 q->p_flag &= ~P_TRACED;
923 if (q->sigwait_thread) {
9bccf70c
A
924 thread_t sig_shuttle;
925
926 sig_shuttle = (thread_t) getshuttle_thread((thread_act_t)q->sigwait_thread);
0b4e3aa0
A
927 /*
928 * The sigwait_thread could be stopped at a
929 * breakpoint. Wake it up to kill.
930 * Need to do this as it could be a thread which is not
931 * the first thread in the task. So any attempts to kill
932 * the process would result into a deadlock on q->sigwait.
933 */
9bccf70c 934 thread_resume((thread_act_t)q->sigwait_thread);
0b4e3aa0 935 clear_wait(sig_shuttle, THREAD_INTERRUPTED);
9bccf70c 936 threadsignal((thread_act_t)q->sigwait_thread, SIGKILL, 0);
0b4e3aa0
A
937 }
938 psignal(q, SIGKILL);
939 }
940 }
941
0b4e3aa0
A
942 /*
943 * Save exit status and final rusage info, adding in child rusage
944 * info and self times.
945 */
946 *p->p_ru = p->p_stats->p_ru;
947
948 timerclear(&p->p_ru->ru_utime);
949 timerclear(&p->p_ru->ru_stime);
950
951#ifdef FIXME
952 if (task) {
953 task_basic_info_data_t tinfo;
954 task_thread_times_info_data_t ttimesinfo;
955 int task_info_stuff, task_ttimes_stuff;
956 struct timeval ut,st;
957
958 task_info_stuff = TASK_BASIC_INFO_COUNT;
959 task_info(task, TASK_BASIC_INFO,
960 &tinfo, &task_info_stuff);
961 p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds;
962 p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds;
963 p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds;
964 p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds;
965
966 task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT;
967 task_info(task, TASK_THREAD_TIMES_INFO,
968 &ttimesinfo, &task_ttimes_stuff);
969
970 ut.tv_sec = ttimesinfo.user_time.seconds;
971 ut.tv_usec = ttimesinfo.user_time.microseconds;
972 st.tv_sec = ttimesinfo.system_time.seconds;
973 st.tv_usec = ttimesinfo.system_time.microseconds;
974 timeradd(&ut,&p->p_ru->ru_utime,&p->p_ru->ru_utime);
975 timeradd(&st,&p->p_ru->ru_stime,&p->p_ru->ru_stime);
976 }
977#endif /* FIXME */
978
979 ruadd(p->p_ru, &p->p_stats->p_cru);
980
981 /*
982 * Free up profiling buffers.
983 */
984 {
985 struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn;
986
987 p1 = p0->pr_next;
988 p0->pr_next = NULL;
989 p0->pr_scale = 0;
990
991 for (; p1 != NULL; p1 = pn) {
992 pn = p1->pr_next;
993 kfree((vm_offset_t)p1, sizeof *p1);
994 }
995 }
996
997 /*
998 * Other substructures are freed from wait().
999 */
1000 FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC);
1001 p->p_stats = NULL;
1002
1003 FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC);
1004 p->p_sigacts = NULL;
1005
1006 if (--p->p_limit->p_refcnt == 0)
1007 FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
1008 p->p_limit = NULL;
1009
1010 /*
1011 * Finish up by terminating the task
1012 * and halt this thread (only if a
1013 * member of the task exiting).
1014 */
1015 p->task = TASK_NULL;
1016
1017 /*
1018 * Notify parent that we're gone.
1019 */
9bccf70c
A
1020 pp = p->p_pptr;
1021 if (pp != initproc) {
1022 pp->si_pid = p->p_pid;
1023 pp->si_status = p->p_xstat;
1024 pp->si_code = CLD_EXITED;
1025 pp->si_uid = p->p_cred->p_ruid;
1026 }
0b4e3aa0
A
1027 psignal(p->p_pptr, SIGCHLD);
1028
1029 /* Place onto zombproc. */
1030 LIST_INSERT_HEAD(&zombproc, p, p_list);
1031 p->p_stat = SZOMB;
1032
1033 /* and now wakeup the parent */
1034 wakeup((caddr_t)p->p_pptr);
0b4e3aa0 1035}