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