From 4fdb9580fedac9669508bef0837f46f1e9310e24 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Mon, 17 Aug 2015 21:01:35 +0200 Subject: [PATCH] Wait for compiler subprocess 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). --- NEWS.txt | 4 ++++ ccache.c | 13 +++++++++++-- ccache.h | 2 +- execute.c | 12 ++++++------ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 2776836f8..257d71b9f 100644 --- 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 ------------ diff --git a/ccache.c b/ccache.c index d47b1919e..8012f96b7 100644 --- 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); } diff --git a/ccache.h b/ccache.h index 819b7a437..d3ecf6c0c 100644 --- 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); diff --git a/execute.c b/execute.c index f48e67cea..109d60e09 100644 --- 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; -- 2.47.2