xref: /netbsd-src/lib/libc/stdlib/quick_exit.c (revision f5c1f2146c11935f9a9a5516fc35e3ad74750975)
1*f5c1f214Schristos /*	$NetBSD: quick_exit.c,v 1.1 2013/04/26 18:29:55 christos Exp $	*/
2*f5c1f214Schristos 
3*f5c1f214Schristos /*-
4*f5c1f214Schristos  * Copyright (c) 2011 David Chisnall
5*f5c1f214Schristos  * All rights reserved.
6*f5c1f214Schristos  *
7*f5c1f214Schristos  * Redistribution and use in source and binary forms, with or without
8*f5c1f214Schristos  * modification, are permitted provided that the following conditions
9*f5c1f214Schristos  * are met:
10*f5c1f214Schristos  * 1. Redistributions of source code must retain the above copyright
11*f5c1f214Schristos  *    notice, this list of conditions and the following disclaimer.
12*f5c1f214Schristos  * 2. Redistributions in binary form must reproduce the above copyright
13*f5c1f214Schristos  *    notice, this list of conditions and the following disclaimer in the
14*f5c1f214Schristos  *    documentation and/or other materials provided with the distribution.
15*f5c1f214Schristos  *
16*f5c1f214Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*f5c1f214Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*f5c1f214Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*f5c1f214Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*f5c1f214Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c1f214Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*f5c1f214Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*f5c1f214Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*f5c1f214Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*f5c1f214Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*f5c1f214Schristos  * SUCH DAMAGE.
27*f5c1f214Schristos  *
28*f5c1f214Schristos  * $FreeBSD: src/lib/libc/stdlib/quick_exit.c,v 1.4 2012/11/17 01:49:41 svnexp Exp $
29*f5c1f214Schristos  */
30*f5c1f214Schristos #include <sys/cdefs.h>
31*f5c1f214Schristos __RCSID("$NetBSD: quick_exit.c,v 1.1 2013/04/26 18:29:55 christos Exp $");
32*f5c1f214Schristos 
33*f5c1f214Schristos #include "namespace.h"
34*f5c1f214Schristos #include "reentrant.h"
35*f5c1f214Schristos 
36*f5c1f214Schristos #include <stdlib.h>
37*f5c1f214Schristos 
38*f5c1f214Schristos /**
39*f5c1f214Schristos  * Linked list of quick exit handlers.  This is simpler than the atexit()
40*f5c1f214Schristos  * version, because it is not required to support C++ destructors or
41*f5c1f214Schristos  * DSO-specific cleanups.
42*f5c1f214Schristos  */
43*f5c1f214Schristos struct quick_exit_handler {
44*f5c1f214Schristos 	struct quick_exit_handler *next;
45*f5c1f214Schristos 	void (*cleanup)(void);
46*f5c1f214Schristos };
47*f5c1f214Schristos 
48*f5c1f214Schristos /**
49*f5c1f214Schristos  * Lock protecting the handlers list.
50*f5c1f214Schristos  */
51*f5c1f214Schristos #ifdef _REENTRANT
52*f5c1f214Schristos extern mutex_t __atexit_mutex;
53*f5c1f214Schristos #endif
54*f5c1f214Schristos 
55*f5c1f214Schristos /**
56*f5c1f214Schristos  * Stack of cleanup handlers.  These will be invoked in reverse order when
57*f5c1f214Schristos  */
58*f5c1f214Schristos static struct quick_exit_handler *handlers;
59*f5c1f214Schristos 
60*f5c1f214Schristos int
at_quick_exit(void (* func)(void))61*f5c1f214Schristos at_quick_exit(void (*func)(void))
62*f5c1f214Schristos {
63*f5c1f214Schristos 	struct quick_exit_handler *h;
64*f5c1f214Schristos 
65*f5c1f214Schristos 	h = malloc(sizeof(*h));
66*f5c1f214Schristos 
67*f5c1f214Schristos 	if (NULL == h)
68*f5c1f214Schristos 		return 1;
69*f5c1f214Schristos 	h->cleanup = func;
70*f5c1f214Schristos #ifdef _REENTRANT
71*f5c1f214Schristos 	mutex_lock(&__atexit_mutex);
72*f5c1f214Schristos #endif
73*f5c1f214Schristos 	h->next = handlers;
74*f5c1f214Schristos 	handlers = h;
75*f5c1f214Schristos #ifdef _REENTRANT
76*f5c1f214Schristos 	mutex_unlock(&__atexit_mutex);
77*f5c1f214Schristos #endif
78*f5c1f214Schristos 	return 0;
79*f5c1f214Schristos }
80*f5c1f214Schristos 
81*f5c1f214Schristos void
quick_exit(int status)82*f5c1f214Schristos quick_exit(int status)
83*f5c1f214Schristos {
84*f5c1f214Schristos 	struct quick_exit_handler *h;
85*f5c1f214Schristos 
86*f5c1f214Schristos 	/*
87*f5c1f214Schristos 	 * XXX: The C++ spec requires us to call std::terminate if there is an
88*f5c1f214Schristos 	 * exception here.
89*f5c1f214Schristos 	 */
90*f5c1f214Schristos 	for (h = handlers; NULL != h; h = h->next)
91*f5c1f214Schristos 		(*h->cleanup)();
92*f5c1f214Schristos 	_Exit(status);
93*f5c1f214Schristos }
94