xref: /freebsd/sys/kern/kern_exit.c (revision 0fddbf874719b9bd50cf66ac26d1140bb3f2be69)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
39  * $FreeBSD$
40  */
41 
42 #include "opt_compat.h"
43 #include "opt_ktrace.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/sysproto.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/lock.h>
51 #include <sys/mutex.h>
52 #include <sys/proc.h>
53 #include <sys/pioctl.h>
54 #include <sys/tty.h>
55 #include <sys/wait.h>
56 #include <sys/vnode.h>
57 #include <sys/resourcevar.h>
58 #include <sys/signalvar.h>
59 #include <sys/sx.h>
60 #include <sys/ptrace.h>
61 #include <sys/acct.h>		/* for acct_process() function prototype */
62 #include <sys/filedesc.h>
63 #include <sys/shm.h>
64 #include <sys/sem.h>
65 #include <sys/aio.h>
66 #include <sys/jail.h>
67 
68 #include <vm/vm.h>
69 #include <vm/vm_param.h>
70 #include <vm/pmap.h>
71 #include <vm/vm_map.h>
72 #include <vm/vm_zone.h>
73 #include <sys/user.h>
74 
75 /* Required to be non-static for SysVR4 emulator */
76 MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status");
77 
78 static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback");
79 
80 static int wait1 __P((struct proc *, struct wait_args *, int));
81 
82 /*
83  * callout list for things to do at exit time
84  */
85 struct exitlist {
86 	exitlist_fn function;
87 	TAILQ_ENTRY(exitlist) next;
88 };
89 
90 TAILQ_HEAD(exit_list_head, exitlist);
91 static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list);
92 
93 /*
94  * exit --
95  *	Death of process.
96  *
97  * MPSAFE
98  */
99 void
100 sys_exit(p, uap)
101 	struct proc *p;
102 	struct sys_exit_args /* {
103 		int	rval;
104 	} */ *uap;
105 {
106 	mtx_lock(&Giant);
107 	exit1(p, W_EXITCODE(uap->rval, 0));
108 	/* NOTREACHED */
109 }
110 
111 /*
112  * Exit: deallocate address space and other resources, change proc state
113  * to zombie, and unlink proc from allproc and parent's lists.  Save exit
114  * status and rusage for wait().  Check for child processes and orphan them.
115  */
116 void
117 exit1(p, rv)
118 	register struct proc *p;
119 	int rv;
120 {
121 	register struct proc *q, *nq;
122 	register struct vmspace *vm;
123 	struct exitlist *ep;
124 
125 	GIANT_REQUIRED;
126 
127 	if (p->p_pid == 1) {
128 		printf("init died (signal %d, exit %d)\n",
129 		    WTERMSIG(rv), WEXITSTATUS(rv));
130 		panic("Going nowhere without my init!");
131 	}
132 
133 	aio_proc_rundown(p);
134 
135 	/* are we a task leader? */
136 	PROC_LOCK(p);
137 	if(p == p->p_leader) {
138 		q = p->p_peers;
139 		while (q != NULL) {
140 			PROC_LOCK(q);
141 			psignal(q, SIGKILL);
142 			PROC_UNLOCK(q);
143 			q = q->p_peers;
144 		}
145 		while (p->p_peers)
146 			msleep((caddr_t)p, &p->p_mtx, PWAIT, "exit1", 0);
147 	}
148 	PROC_UNLOCK(p);
149 
150 #ifdef PGINPROF
151 	vmsizmon();
152 #endif
153 	STOPEVENT(p, S_EXIT, rv);
154 	wakeup(&p->p_stype);	/* Wakeup anyone in procfs' PIOCWAIT */
155 
156 	/*
157 	 * Check if any loadable modules need anything done at process exit.
158 	 * e.g. SYSV IPC stuff
159 	 * XXX what if one of these generates an error?
160 	 */
161 	TAILQ_FOREACH(ep, &exit_list, next)
162 		(*ep->function)(p);
163 
164 	stopprofclock(p);
165 
166 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
167 		M_ZOMBIE, M_WAITOK);
168 	/*
169 	 * If parent is waiting for us to exit or exec,
170 	 * P_PPWAIT is set; we will wakeup the parent below.
171 	 */
172 	PROC_LOCK(p);
173 	p->p_flag &= ~(P_TRACED | P_PPWAIT);
174 	p->p_flag |= P_WEXIT;
175 	SIGEMPTYSET(p->p_siglist);
176 	PROC_UNLOCK(p);
177 	if (timevalisset(&p->p_realtimer.it_value))
178 		callout_stop(&p->p_itcallout);
179 
180 	/*
181 	 * Reset any sigio structures pointing to us as a result of
182 	 * F_SETOWN with our pid.
183 	 */
184 	funsetownlst(&p->p_sigiolst);
185 
186 	/*
187 	 * Close open files and release open-file table.
188 	 * This may block!
189 	 */
190 	fdfree(p);
191 
192 	/*
193 	 * Remove ourself from our leader's peer list and wake our leader.
194 	 */
195 	PROC_LOCK(p->p_leader);
196 	if(p->p_leader->p_peers) {
197 		q = p->p_leader;
198 		while(q->p_peers != p)
199 			q = q->p_peers;
200 		q->p_peers = p->p_peers;
201 		wakeup((caddr_t)p->p_leader);
202 	}
203 	PROC_UNLOCK(p->p_leader);
204 
205 	/*
206 	 * XXX Shutdown SYSV semaphores
207 	 */
208 	semexit(p);
209 
210 	/* The next two chunks should probably be moved to vmspace_exit. */
211 	vm = p->p_vmspace;
212 	/*
213 	 * Release user portion of address space.
214 	 * This releases references to vnodes,
215 	 * which could cause I/O if the file has been unlinked.
216 	 * Need to do this early enough that we can still sleep.
217 	 * Can't free the entire vmspace as the kernel stack
218 	 * may be mapped within that space also.
219 	 */
220 	if (vm->vm_refcnt == 1) {
221 		if (vm->vm_shm)
222 			shmexit(p);
223 		pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS,
224 		    VM_MAXUSER_ADDRESS);
225 		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
226 		    VM_MAXUSER_ADDRESS);
227 	}
228 
229 	PROC_LOCK(p);
230 	if (SESS_LEADER(p)) {
231 		register struct session *sp = p->p_session;
232 
233 		PROC_UNLOCK(p);
234 		if (sp->s_ttyvp) {
235 			/*
236 			 * Controlling process.
237 			 * Signal foreground pgrp,
238 			 * drain controlling terminal
239 			 * and revoke access to controlling terminal.
240 			 */
241 			if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) {
242 				if (sp->s_ttyp->t_pgrp)
243 					pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
244 				(void) ttywait(sp->s_ttyp);
245 				/*
246 				 * The tty could have been revoked
247 				 * if we blocked.
248 				 */
249 				if (sp->s_ttyvp)
250 					VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
251 			}
252 			if (sp->s_ttyvp)
253 				vrele(sp->s_ttyvp);
254 			sp->s_ttyvp = NULL;
255 			/*
256 			 * s_ttyp is not zero'd; we use this to indicate
257 			 * that the session once had a controlling terminal.
258 			 * (for logging and informational purposes)
259 			 */
260 		}
261 		sp->s_leader = NULL;
262 	} else
263 		PROC_UNLOCK(p);
264 	fixjobc(p, p->p_pgrp, 0);
265 	(void)acct_process(p);
266 #ifdef KTRACE
267 	/*
268 	 * release trace file
269 	 */
270 	p->p_traceflag = 0;	/* don't trace the vrele() */
271 	if (p->p_tracep)
272 		vrele(p->p_tracep);
273 #endif
274 	/*
275 	 * Remove proc from allproc queue and pidhash chain.
276 	 * Place onto zombproc.  Unlink from parent's child list.
277 	 */
278 	sx_xlock(&allproc_lock);
279 	LIST_REMOVE(p, p_list);
280 	LIST_INSERT_HEAD(&zombproc, p, p_list);
281 	LIST_REMOVE(p, p_hash);
282 	sx_xunlock(&allproc_lock);
283 
284 	sx_xlock(&proctree_lock);
285 	q = LIST_FIRST(&p->p_children);
286 	if (q != NULL)		/* only need this if any child is S_ZOMB */
287 		wakeup((caddr_t) initproc);
288 	for (; q != NULL; q = nq) {
289 		nq = LIST_NEXT(q, p_sibling);
290 		PROC_LOCK(q);
291 		proc_reparent(q, initproc);
292 		q->p_sigparent = SIGCHLD;
293 		/*
294 		 * Traced processes are killed
295 		 * since their existence means someone is screwing up.
296 		 */
297 		if (q->p_flag & P_TRACED) {
298 			q->p_flag &= ~P_TRACED;
299 			psignal(q, SIGKILL);
300 		}
301 		PROC_UNLOCK(q);
302 	}
303 
304 	/*
305 	 * Save exit status and final rusage info, adding in child rusage
306 	 * info and self times.
307 	 */
308 	p->p_xstat = rv;
309 	*p->p_ru = p->p_stats->p_ru;
310 	mtx_lock_spin(&sched_lock);
311 	calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL);
312 	mtx_unlock_spin(&sched_lock);
313 	ruadd(p->p_ru, &p->p_stats->p_cru);
314 
315 	/*
316 	 * Pretend that an mi_switch() to the next process occurs now.  We
317 	 * must set `switchtime' directly since we will call cpu_switch()
318 	 * directly.  Set it now so that the rest of the exit time gets
319 	 * counted somewhere if possible.
320 	 */
321 	mtx_lock_spin(&sched_lock);
322 	microuptime(PCPU_PTR(switchtime));
323 	PCPU_SET(switchticks, ticks);
324 	mtx_unlock_spin(&sched_lock);
325 
326 	/*
327 	 * notify interested parties of our demise.
328 	 */
329 	PROC_LOCK(p);
330 	KNOTE(&p->p_klist, NOTE_EXIT);
331 
332 	/*
333 	 * Notify parent that we're gone.  If parent has the PS_NOCLDWAIT
334 	 * flag set, notify process 1 instead (and hope it will handle
335 	 * this situation).
336 	 */
337 	if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) {
338 		struct proc *pp = p->p_pptr;
339 		proc_reparent(p, initproc);
340 		/*
341 		 * If this was the last child of our parent, notify
342 		 * parent, so in case he was wait(2)ing, he will
343 		 * continue.
344 		 */
345 		if (LIST_EMPTY(&pp->p_children))
346 			wakeup((caddr_t)pp);
347 	}
348 
349 	PROC_LOCK(p->p_pptr);
350 	if (p->p_sigparent && p->p_pptr != initproc)
351 	        psignal(p->p_pptr, p->p_sigparent);
352 	else
353 	        psignal(p->p_pptr, SIGCHLD);
354 	PROC_UNLOCK(p->p_pptr);
355 
356 	/*
357 	 * If this is a kthread, then wakeup anyone waiting for it to exit.
358 	 */
359 	if (p->p_flag & P_KTHREAD)
360 		wakeup((caddr_t)p);
361 	PROC_UNLOCK(p);
362 	sx_xunlock(&proctree_lock);
363 
364 	/*
365 	 * Clear curproc after we've done all operations
366 	 * that could block, and before tearing down the rest
367 	 * of the process state that might be used from clock, etc.
368 	 * Also, can't clear curproc while we're still runnable,
369 	 * as we're not on a run queue (we are current, just not
370 	 * a proper proc any longer!).
371 	 *
372 	 * Other substructures are freed from wait().
373 	 */
374 	mtx_assert(&Giant, MA_OWNED);
375 	if (--p->p_limit->p_refcnt == 0) {
376 		FREE(p->p_limit, M_SUBPROC);
377 		p->p_limit = NULL;
378 	}
379 
380 	/*
381 	 * Finally, call machine-dependent code to release the remaining
382 	 * resources including address space, the kernel stack and pcb.
383 	 * The address space is released by "vmspace_free(p->p_vmspace)";
384 	 * This is machine-dependent, as we may have to change stacks
385 	 * or ensure that the current one isn't reallocated before we
386 	 * finish.  cpu_exit will end with a call to cpu_switch(), finishing
387 	 * our execution (pun intended).
388 	 */
389 	cpu_exit(p);
390 }
391 
392 #ifdef COMPAT_43
393 /*
394  * MPSAFE, the dirty work is handled by wait1().
395  */
396 int
397 owait(p, uap)
398 	struct proc *p;
399 	register struct owait_args /* {
400 		int     dummy;
401 	} */ *uap;
402 {
403 	struct wait_args w;
404 
405 	w.options = 0;
406 	w.rusage = NULL;
407 	w.pid = WAIT_ANY;
408 	w.status = NULL;
409 	return (wait1(p, &w, 1));
410 }
411 #endif /* COMPAT_43 */
412 
413 /*
414  * MPSAFE, the dirty work is handled by wait1().
415  */
416 int
417 wait4(p, uap)
418 	struct proc *p;
419 	struct wait_args *uap;
420 {
421 	return (wait1(p, uap, 0));
422 }
423 
424 /*
425  * MPSAFE
426  */
427 static int
428 wait1(q, uap, compat)
429 	register struct proc *q;
430 	register struct wait_args /* {
431 		int pid;
432 		int *status;
433 		int options;
434 		struct rusage *rusage;
435 	} */ *uap;
436 	int compat;
437 {
438 	register int nfound;
439 	register struct proc *p, *t;
440 	int status, error;
441 
442 	mtx_lock(&Giant);
443 	if (uap->pid == 0)
444 		uap->pid = -q->p_pgid;
445 	if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) {
446 		error = EINVAL;
447 		goto done2;
448 	}
449 loop:
450 	nfound = 0;
451 	sx_slock(&proctree_lock);
452 	LIST_FOREACH(p, &q->p_children, p_sibling) {
453 		if (uap->pid != WAIT_ANY &&
454 		    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
455 			continue;
456 
457 		/*
458 		 * This special case handles a kthread spawned by linux_clone
459 		 * (see linux_misc.c).  The linux_wait4 and linux_waitpid
460 		 * functions need to be able to distinguish between waiting
461 		 * on a process and waiting on a thread.  It is a thread if
462 		 * p_sigparent is not SIGCHLD, and the WLINUXCLONE option
463 		 * signifies we want to wait for threads and not processes.
464 		 */
465 		PROC_LOCK(p);
466 		if ((p->p_sigparent != SIGCHLD) ^
467 		    ((uap->options & WLINUXCLONE) != 0)) {
468 			PROC_UNLOCK(p);
469 			continue;
470 		}
471 
472 		nfound++;
473 		mtx_lock_spin(&sched_lock);
474 		if (p->p_stat == SZOMB) {
475 			/* charge childs scheduling cpu usage to parent */
476 			if (curproc->p_pid != 1) {
477 				curproc->p_estcpu =
478 				    ESTCPULIM(curproc->p_estcpu + p->p_estcpu);
479 			}
480 
481 			mtx_unlock_spin(&sched_lock);
482 			PROC_UNLOCK(p);
483 			sx_sunlock(&proctree_lock);
484 
485 			q->p_retval[0] = p->p_pid;
486 #ifdef COMPAT_43
487 			if (compat)
488 				q->p_retval[1] = p->p_xstat;
489 			else
490 #endif
491 			if (uap->status) {
492 				status = p->p_xstat;	/* convert to int */
493 				if ((error = copyout((caddr_t)&status,
494 				    (caddr_t)uap->status, sizeof(status)))) {
495 					goto done2;
496 				}
497 			}
498 			if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
499 			    (caddr_t)uap->rusage, sizeof (struct rusage)))) {
500 				goto done2;
501 			}
502 			/*
503 			 * If we got the child via a ptrace 'attach',
504 			 * we need to give it back to the old parent.
505 			 */
506 			sx_xlock(&proctree_lock);
507 			if (p->p_oppid) {
508 				if ((t = pfind(p->p_oppid)) != NULL) {
509 					PROC_LOCK(p);
510 					p->p_oppid = 0;
511 					proc_reparent(p, t);
512 					PROC_UNLOCK(p);
513 					psignal(t, SIGCHLD);
514 					wakeup((caddr_t)t);
515 					PROC_UNLOCK(t);
516 					sx_xunlock(&proctree_lock);
517 					error = 0;
518 					goto done2;
519 				}
520 			}
521 			sx_xunlock(&proctree_lock);
522 			PROC_LOCK(p);
523 			p->p_xstat = 0;
524 			PROC_UNLOCK(p);
525 			ruadd(&q->p_stats->p_cru, p->p_ru);
526 			FREE(p->p_ru, M_ZOMBIE);
527 			p->p_ru = NULL;
528 
529 			/*
530 			 * Decrement the count of procs running with this uid.
531 			 */
532 			(void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0);
533 
534 			/*
535 			 * Release reference to text vnode
536 			 */
537 			if (p->p_textvp)
538 				vrele(p->p_textvp);
539 
540 			/*
541 			 * Finally finished with old proc entry.
542 			 * Unlink it from its process group and free it.
543 			 */
544 			leavepgrp(p);
545 
546 			sx_xlock(&allproc_lock);
547 			LIST_REMOVE(p, p_list);	/* off zombproc */
548 			sx_xunlock(&allproc_lock);
549 
550 			sx_xlock(&proctree_lock);
551 			LIST_REMOVE(p, p_sibling);
552 			sx_xunlock(&proctree_lock);
553 
554 			/*
555 			 * Free up credentials.
556 			 */
557 			crfree(p->p_ucred);
558 			p->p_ucred = NULL;
559 
560 			/*
561 			 * Remove unused arguments
562 			 */
563 			if (p->p_args && --p->p_args->ar_ref == 0)
564 				FREE(p->p_args, M_PARGS);
565 
566 			if (--p->p_procsig->ps_refcnt == 0) {
567 				if (p->p_sigacts != &p->p_addr->u_sigacts)
568 					FREE(p->p_sigacts, M_SUBPROC);
569 			        FREE(p->p_procsig, M_SUBPROC);
570 				p->p_procsig = NULL;
571 			}
572 
573 			/*
574 			 * Give machine-dependent layer a chance
575 			 * to free anything that cpu_exit couldn't
576 			 * release while still running in process context.
577 			 */
578 			cpu_wait(p);
579 			mtx_destroy(&p->p_mtx);
580 			zfree(proc_zone, p);
581 			nprocs--;
582 			error = 0;
583 			goto done2;
584 		}
585 		if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
586 		    (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
587 			mtx_unlock_spin(&sched_lock);
588 			p->p_flag |= P_WAITED;
589 			PROC_UNLOCK(p);
590 			sx_sunlock(&proctree_lock);
591 			q->p_retval[0] = p->p_pid;
592 #ifdef COMPAT_43
593 			if (compat) {
594 				q->p_retval[1] = W_STOPCODE(p->p_xstat);
595 				error = 0;
596 			} else
597 #endif
598 			if (uap->status) {
599 				status = W_STOPCODE(p->p_xstat);
600 				error = copyout((caddr_t)&status,
601 					(caddr_t)uap->status, sizeof(status));
602 			} else
603 				error = 0;
604 			goto done2;
605 		}
606 		mtx_unlock_spin(&sched_lock);
607 		PROC_UNLOCK(p);
608 	}
609 	sx_sunlock(&proctree_lock);
610 	if (nfound == 0) {
611 		error = ECHILD;
612 		goto done2;
613 	}
614 	if (uap->options & WNOHANG) {
615 		q->p_retval[0] = 0;
616 		error = 0;
617 		goto done2;
618 	}
619 	if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) != 0)
620 		goto done2;
621 	goto loop;
622 done2:
623 	mtx_unlock(&Giant);
624 	return(error);
625 }
626 
627 /*
628  * Make process 'parent' the new parent of process 'child'.
629  * Must be called with an exclusive hold of proctree lock.
630  */
631 void
632 proc_reparent(child, parent)
633 	register struct proc *child;
634 	register struct proc *parent;
635 {
636 
637 	SX_ASSERT_XLOCKED(&proctree_lock);
638 	PROC_LOCK_ASSERT(child, MA_OWNED);
639 	if (child->p_pptr == parent)
640 		return;
641 
642 	LIST_REMOVE(child, p_sibling);
643 	LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
644 	child->p_pptr = parent;
645 }
646 
647 /*
648  * The next two functions are to handle adding/deleting items on the
649  * exit callout list
650  *
651  * at_exit():
652  * Take the arguments given and put them onto the exit callout list,
653  * However first make sure that it's not already there.
654  * returns 0 on success.
655  */
656 
657 int
658 at_exit(function)
659 	exitlist_fn function;
660 {
661 	struct exitlist *ep;
662 
663 #ifdef INVARIANTS
664 	/* Be noisy if the programmer has lost track of things */
665 	if (rm_at_exit(function))
666 		printf("WARNING: exit callout entry (%p) already present\n",
667 		    function);
668 #endif
669 	ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT);
670 	if (ep == NULL)
671 		return (ENOMEM);
672 	ep->function = function;
673 	TAILQ_INSERT_TAIL(&exit_list, ep, next);
674 	return (0);
675 }
676 
677 /*
678  * Scan the exit callout list for the given item and remove it.
679  * Returns the number of items removed (0 or 1)
680  */
681 int
682 rm_at_exit(function)
683 	exitlist_fn function;
684 {
685 	struct exitlist *ep;
686 
687 	TAILQ_FOREACH(ep, &exit_list, next) {
688 		if (ep->function == function) {
689 			TAILQ_REMOVE(&exit_list, ep, next);
690 			free(ep, M_ATEXIT);
691 			return(1);
692 		}
693 	}
694 	return (0);
695 }
696