From: Joel Rosdahl Date: Wed, 14 Jul 2010 16:13:23 +0000 (+0200) Subject: Add exit functions functionality X-Git-Tag: v3.1~199 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a417ea68b2fe2e7d236bfb57ffadad59faef0529;p=thirdparty%2Fccache.git Add exit functions functionality --- diff --git a/Makefile.in b/Makefile.in index c9e3676f7..42f902c91 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,7 @@ libs = @LIBS@ -lm sources = \ ccache.c mdfour.c hash.c execute.c util.c args.c stats.c version.c \ cleanup.c snprintf.c unify.c manifest.c hashtable.c hashtable_itr.c \ - murmurhashneutral2.c hashutil.c getopt_long.c + murmurhashneutral2.c hashutil.c getopt_long.c exitfn.c all_sources = $(sources) @extra_sources@ headers = \ diff --git a/ccache.c b/ccache.c index 1017ad237..a1332bfd2 100644 --- a/ccache.c +++ b/ccache.c @@ -284,6 +284,7 @@ static void failed(void) cc_log("Failed; falling back to running the real compiler"); cc_log_executed_command(orig_args->argv); + exitfn_call(); execv(orig_args->argv[0], orig_args->argv); fatal("%s: execv returned (%s)", orig_args->argv[0], strerror(errno)); } @@ -2138,6 +2139,8 @@ int main(int argc, char *argv[]) char *p; char *program_name; + exitfn_init(); + /* check for logging early so cc_log messages start working ASAP */ cache_logfile = getenv("CCACHE_LOGFILE"); cc_log("=== CCACHE STARTED ========================================="); diff --git a/ccache.h b/ccache.h index 68be2ae1c..5c155f06a 100644 --- a/ccache.h +++ b/ccache.h @@ -122,6 +122,11 @@ void stats_set_sizes(const char *dir, size_t num_files, size_t total_size); int unify_hash(struct mdfour *hash, const char *fname); +void exitfn_init(void); +void exitfn_add_nullary(void (*function)(void)); +void exitfn_add(void (*function)(void *), void *context); +void exitfn_call(void); + #ifndef HAVE_VASPRINTF int vasprintf(char **, const char *, va_list) ATTR_FORMAT(printf, 2, 0); #endif diff --git a/exitfn.c b/exitfn.c new file mode 100644 index 000000000..0a8179322 --- /dev/null +++ b/exitfn.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 Joel Rosdahl + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ccache.h" +#include +#include +#include + +struct exit_function { + void (*function)(void *); + void *context; + struct exit_function *next; +}; + +struct nullary_exit_function { + void (*function)(void); +}; + +static struct exit_function *exit_functions; + +static void +call_nullary_exit_function(void *context) +{ + struct nullary_exit_function *p = (struct nullary_exit_function*)context; + p->function(); + free(p); +} + +/* + * Initialize exit functions. Must be called once before exitfn_add* are used. + */ +void +exitfn_init(void) +{ + if (atexit(exitfn_call) != 0) { + fatal("atexit failed: %s", strerror(errno)); + } +} + +/* + * Add a nullary function to be called context when ccache exits. Functions are + * called in reverse order. + */ +void +exitfn_add_nullary(void (*function)(void)) +{ + struct nullary_exit_function *p = x_malloc(sizeof(*p)); + p->function = function; + exitfn_add(call_nullary_exit_function, p); +} + +/* + * Add a function to be called with a context parameter when ccache exits. + * Functions are called in reverse order. + */ +void +exitfn_add(void (*function)(void *), void *context) +{ + struct exit_function *p; + + p = x_malloc(sizeof(*p)); + p->function = function; + p->context = context; + p->next = exit_functions; + exit_functions = p; +} + +/* + * Call added functions. + */ +void +exitfn_call(void) +{ + struct exit_function *p = exit_functions, *q; + while (p) { + p->function(p->context); + q = p; + p = p->next; + free(q); + } +}