]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Avoid calling exit() inside an exit handler
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 3 Jun 2015 19:10:46 +0000 (21:10 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 3 Jun 2015 19:13:02 +0000 (21:13 +0200)
NEWS.txt
ccache.c
ccache.h
execute.c
exitfn.c
util.c

index 22fe37836ea2bc35ee641b1751025b38751a5f2f..cd622411d68baba76bbab282140c3c2f2dc04838 100644 (file)
--- 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
 ------------
index cb7e72eac9b1f66a251f3d45a82de098393fabd1..0b56946632bc291a9a3ed0cb00b71fc11a2bf492 100644 (file)
--- 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 */
index 6028f46c66704126d1eea4ebe44ada9bb3037292..819b7a4379a90647dd26defd367137154030b23d 100644 (file)
--- 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);
index 94d605dc6ad43a8df0855fdde122c8a1908aec28..3b57a69713af7e8229fd3229bf184ddbffb86b7a 100644 (file)
--- 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);
index bf98e5ec741a6a91517c0b4c522c1a507464043b..5d76eeeada72f4f249bd4ceacbc692499aeba754 100644 (file)
--- 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 658cab6a94a875d37db66c30796bccfa2e3a7799..5cc9795cc1b2884877c35694d62d6f328e523aef 100644 (file)
--- 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)
 {