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