Implement quick_exit() / at_quick_exit() from C++11 / C1x. Also add a

__noreturn macro and modify the other exiting functions to use it.

The __noreturn macro, unlike __dead2, must be used BEFORE the function.
This is in line with the C and C++ specifications that place _Noreturn (c1x)
and [[noreturn]] (C++11) in front of the functions.  As with __dead2, this
macro falls back to using the GCC attribute.

Unfortunately, clang currently sets the same value for the C version macro
in C99 and C1x modes, so these functions are hidden by default.  At some
point before 10.0, I need to go through the headers and clean up the C1x /
C++11 visibility.

Reviewed by:	brooks (mentor)
This commit is contained in:
David Chisnall 2011-12-07 15:25:48 +00:00
parent 6d18ea8ff9
commit 0a31efe016
9 changed files with 226 additions and 6 deletions

View File

@ -76,7 +76,7 @@ extern int __mb_cur_max;
extern int ___mb_cur_max(void);
#define MB_CUR_MAX (___mb_cur_max())
void abort(void) __dead2;
__noreturn void abort(void);
int abs(int) __pure2;
int atexit(void (*)(void));
double atof(const char *);
@ -86,7 +86,7 @@ void *bsearch(const void *, const void *, size_t,
size_t, int (*)(const void *, const void *));
void *calloc(size_t, size_t) __malloc_like;
div_t div(int, int) __pure2;
void exit(int) __dead2;
__noreturn void exit(int);
void free(void *);
char *getenv(const char *);
long labs(long) __pure2;
@ -145,9 +145,17 @@ unsigned long long
strtoull(const char * __restrict, char ** __restrict, int);
#endif /* __LONG_LONG_SUPPORTED */
void _Exit(int) __dead2;
__noreturn void _Exit(int);
#endif /* __ISO_C_VISIBLE >= 1999 */
/*
* If we're in a mode greater than C99, expose C1x functions.
*/
#if __ISO_C_VISIBLE > 1999
__noreturn void quick_exit(int)
int
at_quick_exit(void (*func)(void));
#endif /* __ISO_C_VISIBLE > 1999 */
/*
* Extensions made by POSIX relative to C. We don't know yet which edition
* of POSIX made these extensions, so assume they've always been there until

View File

@ -8,8 +8,8 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
bsearch.c div.c exit.c getenv.c getopt.c getopt_long.c \
getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \
merge.c ptsname.c qsort.c qsort_r.c radixsort.c rand.c random.c \
reallocf.c realpath.c remque.c strfmon.c strtoimax.c \
merge.c ptsname.c qsort.c qsort_r.c quick_exit.c radixsort.c rand.c \
random.c reallocf.c realpath.c remque.c strfmon.c strtoimax.c \
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
@ -18,10 +18,12 @@ SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
# machine-dependent stdlib sources
.sinclude "${.CURDIR}/${LIBC_ARCH}/stdlib/Makefile.inc"
MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \
MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 \
at_quick_exit.3 bsearch.3 \
div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \
hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
lsearch.3 malloc.3 memory.3 posix_memalign.3 ptsname.3 qsort.3 \
quick_exit.3 \
radixsort.3 rand.3 random.3 \
realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \
tsearch.3

View File

@ -97,6 +97,8 @@ FBSD_1.3 {
atoi_l;
atol_l;
atoll_l;
at_quick_exit;
quick_exit;
strtod_l;
strtol_l;
strtoll_l;

View File

@ -0,0 +1,58 @@
.\" Copyright (c) 2011 David Chisnall
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\" /
.Dd December 7, 2011o.Dt ATEXIT 3
.Dt AT_QUICK_EXIT 3
.Os
.Sh NAME
.Nm at_quick_exit
.Nd Registers a cleanup function to run on quick exit.
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In stdlib.h
.Ft int
.Fn at_quick_exit "void (*func)(void)"
.Sh DESCRIPTION
The
.Fn at_quick_exit
function registers a cleanup function to be called when the program exits as a
result of calling
.Xr quick_exit 3 .
The cleanup functions are called in the reverse order and will not be called if
the program exits by calling
.Xr exit 3 ,
.Xr _Exit 3 ,
or
.Xr abort 3 .
.El
.Sh SEE ALSO
.Xr exit 3 ,
.Xr at_quick_exit 3
.Sh STANDARDS
The
.Fn at_quick_exit
function conforms to the C1x draft specification.

View File

@ -79,6 +79,7 @@ No memory was available to add the function to the list.
The existing list of functions is unmodified.
.El
.Sh SEE ALSO
.Xr at_quick_exit 3
.Xr exit 3
.Sh STANDARDS
The

View File

@ -118,7 +118,9 @@ never return.
.Xr _exit 2 ,
.Xr wait 2 ,
.Xr atexit 3 ,
.Xr at_quick_exit 3 ,
.Xr intro 3 ,
.Xr quick_exit 3 ,
.Xr sysexits 3 ,
.Xr tmpfile 3
.Sh STANDARDS

View File

@ -0,0 +1,55 @@
.\" Copyright (c) 2011 David Chisnall
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\" /
.Dd December 7, 2011o.Dt ATEXIT 3
.Dt QUICK_EXIT 3
.Os
.Sh NAME
.Nm quick_exit
.Nd Exits a program quickly, running minimal cleanup
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In stdlib.h
.Ft _Noreturn void
.Fn quick_exit "void"
.Sh DESCRIPTION
The
.Fn quick_exit
function exits the program quickly calling any cleanup functions registered
with
.Xr at_quick_exit 3
but not any C++ destructors or cleanup code registered with
.Xr atexit 3 .
.El
.Sh SEE ALSO
.Xr exit 3 ,
.Xr at_quick_exit 3
.Sh STANDARDS
The
.Fn quick_exit
function conforms to the C1x draft specification.

View File

@ -0,0 +1,81 @@
/*-
* Copyright (c) 2011 David Chisnall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stdlib.h>
#include <pthread.h>
/**
* Linked list of quick exit handlers. This is simpler than the atexit()
* version, because it is not required to support C++ destructors or
* DSO-specific cleanups.
*/
struct quick_exit_handler {
struct quick_exit_handler *next;
void (*cleanup)(void);
};
__attribute((weak))
void _ZSt9terminatev(void);
/**
* Lock protecting the handlers list.
*/
static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Stack of cleanup handlers. These will be invoked in reverse order when
*/
static struct quick_exit_handler *handlers;
int
at_quick_exit(void (*func)(void))
{
struct quick_exit_handler *h = malloc(sizeof(struct quick_exit_handler));
if (0 == h) {
return 1;
}
h->cleanup = func;
pthread_mutex_lock(&atexit_mutex);
h->next = handlers;
handlers = h;
pthread_mutex_unlock(&atexit_mutex);
return 0;
}
void quick_exit(int status)
{
/*
* XXX: The C++ spec requires us to call std::terminate if there is an
* exception here.
*/
for (struct quick_exit_handler *h = handlers ; NULL != h ; h = h->next)
{
h->cleanup();
}
_Exit(status);
}

View File

@ -218,6 +218,17 @@
#endif
#endif
#if defined(__cplusplus) && __cplusplus >= 201103L
#define __noreturn [[noreturn]]
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ > 201000L
#define __noreturn _Noreturn
#elif defined(__GNUC__)
#define __noreturn __attribute__((__noreturn__))
#else
#define __noreturn
#endif
#if __GNUC_PREREQ__(2, 96)
#define __malloc_like __attribute__((__malloc__))
#define __pure __attribute__((__pure__))