From 94085e8a219c0015acc27fff99df16ee8ebe60c3 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Wed, 3 Jun 2015 21:10:46 +0200 Subject: [PATCH] Avoid calling exit() inside an exit handler --- NEWS.txt | 2 ++ ccache.c | 14 +++++++------- ccache.h | 1 + execute.c | 4 ++-- exitfn.c | 4 ++-- util.c | 24 ++++++++++++++++++++---- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 22fe37836..cd622411d 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -10,6 +10,8 @@ Bug fixes - Support external zlib in nonstandard directory. +- Avoid calling `exit()` inside an exit handler. + ccache 3.2.2 ------------ diff --git a/ccache.c b/ccache.c index cb7e72eac..0b5694663 100644 --- a/ccache.c +++ b/ccache.c @@ -917,7 +917,7 @@ to_cache(struct args *args) close(fd); tmp_unlink(tmp_stderr); - exit(status); + x_exit(status); } tmp_unlink(tmp_stderr); @@ -1647,7 +1647,7 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) } /* and exit with the right status code */ - exit(0); + x_exit(0); } /* find the real compiler. We just search the PATH to find a executable of the @@ -2864,7 +2864,7 @@ ccache(int argc, char *argv[]) /* run real compiler, sending output to cache */ to_cache(compiler_args); - exit(0); + x_exit(0); } static void @@ -2919,7 +2919,7 @@ ccache_main_options(int argc, char *argv[]) case 'h': /* --help */ fputs(USAGE_TEXT, stdout); - exit(0); + x_exit(0); case 'F': /* --max-files */ { @@ -2990,7 +2990,7 @@ ccache_main_options(int argc, char *argv[]) case 'V': /* --version */ fprintf(stdout, VERSION_TEXT, CCACHE_VERSION); - exit(0); + x_exit(0); case 'z': /* --zero-stats */ initialize(); @@ -3000,7 +3000,7 @@ ccache_main_options(int argc, char *argv[]) default: fputs(USAGE_TEXT, stderr); - exit(1); + x_exit(1); } } @@ -3015,7 +3015,7 @@ ccache_main(int argc, char *argv[]) if (same_executable_name(program_name, MYNAME)) { if (argc < 2) { fputs(USAGE_TEXT, stderr); - exit(1); + x_exit(1); } /* if the first argument isn't an option, then assume we are being passed a compiler name and options */ diff --git a/ccache.h b/ccache.h index 6028f46c6..819b7a437 100644 --- a/ccache.h +++ b/ccache.h @@ -164,6 +164,7 @@ char *get_relative_path(const char *from, const char *to); bool is_absolute_path(const char *path); bool is_full_path(const char *path); void update_mtime(const char *path); +void x_exit(int status) ATTR_NORETURN; int x_rename(const char *oldpath, const char *newpath); int tmp_unlink(const char *path); int x_unlink(const char *path); diff --git a/execute.c b/execute.c index 94d605dc6..3b57a6971 100644 --- a/execute.c +++ b/execute.c @@ -214,7 +214,7 @@ win32execute(char *path, char **argv, int doreturn, CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (!doreturn) - exit(exitcode); + x_exit(exitcode); return exitcode; } @@ -242,7 +242,7 @@ execute(char **argv, int fd_out, int fd_err) close(fd_out); dup2(fd_err, 2); close(fd_err); - exit(execv(argv[0], argv)); + x_exit(execv(argv[0], argv)); } close(fd_out); diff --git a/exitfn.c b/exitfn.c index bf98e5ec7..5d76eeead 100644 --- a/exitfn.c +++ b/exitfn.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 Joel Rosdahl + * Copyright (C) 2010-2015 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 @@ -84,11 +84,11 @@ void exitfn_call(void) { struct exit_function *p = exit_functions, *q; + exit_functions = NULL; while (p) { p->function(p->context); q = p; p = p->next; free(q); } - exit_functions = NULL; } diff --git a/util.c b/util.c index 658cab6a9..5cc9795cc 100644 --- a/util.c +++ b/util.c @@ -118,7 +118,7 @@ warn_log_fail(void) /* Note: Can't call fatal() since that would lead to recursion. */ fprintf(stderr, "ccache: error: Failed to write to %s: %s\n", conf->log_file, strerror(errno)); - exit(EXIT_FAILURE); + x_exit(EXIT_FAILURE); } static void @@ -180,8 +180,9 @@ cc_log_argv(const char *prefix, char **argv) fputs(prefix, logfile); print_command(logfile, argv); rc = fflush(logfile); - if (rc) + if (rc) { warn_log_fail(); + } } /* something went badly wrong! */ @@ -198,7 +199,7 @@ fatal(const char *format, ...) cc_log("FATAL: %s", msg); fprintf(stderr, "ccache: error: %s\n", msg); - exit(1); + x_exit(1); } /* @@ -1425,9 +1426,24 @@ update_mtime(const char *path) } /* - * Rename oldpath to newpath (deleting newpath). + * If exit() already has been called, call _exit(), otherwise exit(). This is + * used to avoid calling exit() inside an atexit handler. */ +void +x_exit(int status) +{ + static bool first_time = true; + if (first_time) { + first_time = false; + exit(status); + } else { + _exit(status); + } +} +/* + * Rename oldpath to newpath (deleting newpath). + */ int x_rename(const char *oldpath, const char *newpath) { -- 2.47.2