]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Wait for compiler subprocess to exit before exiting from a signal
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 17 Aug 2015 19:01:35 +0000 (21:01 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 17 Aug 2015 19:01:35 +0000 (21:01 +0200)
This should fix a race condition (albeit a quite unlikely one) related
to removal of the compiler output file(s).

NEWS.txt
ccache.c
ccache.h
execute.c

index 2776836f86006a7605f9e19c193e493fee95f941..257d71b9f252a3d356a0b68114c817155b281b12 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -14,6 +14,10 @@ Bug fixes
 - Made conversion-to-bool explicit to avoid build warnings (and potential
   runtime errors) on legacy systems.
 
+- Wait for compiler subprocess (if any) to exit before exiting from a signal.
+  This should fix a race condition (albeit a quite unlikely one) related to
+  removal of the compiler output file(s).
+
 
 ccache 3.2.3
 ------------
index d47b1919ee6ae6abd5cd2e8b0185f147d6785865..8012f96b7473bb431cc2bb72615f2c802ff505c3 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -239,6 +239,10 @@ struct pending_tmp_file {
 /* Temporary files to remove at program exit. */
 static struct pending_tmp_file *pending_tmp_files = NULL;
 
+/* PID of currently executing compiler that we have started, if any. 0 means no
+ * ongoing compilation. */
+static pid_t compiler_pid = 0;
+
 /*
  * This is a string that identifies the current "version" of the hash sum
  * computed by ccache. If, for any reason, we want to force the hash sum to be
@@ -339,8 +343,13 @@ clean_up_pending_tmp_files(void)
 static void
 signal_handler(int signo)
 {
+       int status;
        (void)signo;
        clean_up_pending_tmp_files();
+       if (compiler_pid != 0) {
+               /* Wait for compiler subprocess to exit before we snuff it. */
+               waitpid(compiler_pid, &status, 0);
+       }
        _exit(1);
 }
 
@@ -877,7 +886,7 @@ to_cache(struct args *args)
        }
 
        cc_log("Running real compiler");
-       status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd);
+       status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
        args_pop(args, 3);
 
        if (x_stat(tmp_stdout, &st) != 0) {
@@ -1140,7 +1149,7 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash)
                args_add(args, "-E");
                args_add(args, input_file);
                cc_log("Running preprocessor");
-               status = execute(args->argv, path_stdout_fd, path_stderr_fd);
+               status = execute(args->argv, path_stdout_fd, path_stderr_fd, &compiler_pid);
                args_pop(args, 2);
        }
 
index 819b7a4379a90647dd26defd367137154030b23d..d3ecf6c0c0c42c56d8e832e18f5fa0e25fef2ef3 100644 (file)
--- a/ccache.h
+++ b/ccache.h
@@ -213,7 +213,7 @@ void wipe_all(struct conf *conf);
 /* ------------------------------------------------------------------------- */
 /* execute.c */
 
-int execute(char **argv, int fd_out, int fd_err);
+int execute(char **argv, int fd_out, int fd_err, pid_t *pid);
 char *find_executable(const char *name, const char *exclude_name);
 void print_command(FILE *fp, char **argv);
 
index f48e67ceaf7863554c65b6564768cbf82db52ddd..109d60e093df085288b631a5fea13fc3e796add1 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -223,18 +223,17 @@ win32execute(char *path, char **argv, int doreturn,
 /* Execute a compiler backend, capturing all output to the given paths the full
  * path to the compiler to run is in argv[0]. */
 int
-execute(char **argv, int fd_out, int fd_err)
+execute(char **argv, int fd_out, int fd_err, pid_t *pid)
 {
-       pid_t pid;
        int status;
 
        cc_log_argv("Executing ", argv);
-       pid = fork();
-       if (pid == -1) {
+       *pid = fork();
+       if (*pid == -1) {
                fatal("Failed to fork: %s", strerror(errno));
        }
 
-       if (pid == 0) {
+       if (*pid == 0) {
                /* Child. */
                dup2(fd_out, 1);
                close(fd_out);
@@ -246,9 +245,10 @@ execute(char **argv, int fd_out, int fd_err)
        close(fd_out);
        close(fd_err);
 
-       if (waitpid(pid, &status, 0) != pid) {
+       if (waitpid(*pid, &status, 0) != *pid) {
                fatal("waitpid failed: %s", strerror(errno));
        }
+       *pid = 0;
 
        if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
                return -1;