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