From: Joel Rosdahl Date: Wed, 14 May 2014 20:03:53 +0000 (+0200) Subject: Merge branch 'maint' X-Git-Tag: v3.2~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3b69dd690a66bbbb5702e97d475924092fae80d6;p=thirdparty%2Fccache.git Merge branch 'maint' * maint: Fix clang build warning "shift count >= width of type" Clean up stale files in internal tempdir once an hour Add signal handler to clean up temporary files at unexpected program exit Don't needlessly allocate empty counter_updates data in stats_flush() Conflicts: ccache.c manifest.c stats.c --- 3b69dd690a66bbbb5702e97d475924092fae80d6 diff --cc ccache.c index c395fadfd,a6bca4a34..7f72e5320 --- a/ccache.c +++ b/ccache.c @@@ -253,41 -235,75 +261,87 @@@ failed(void cc_log_argv("Executing ", orig_args->argv); exitfn_call(); execv(orig_args->argv[0], orig_args->argv); - fatal("%s: execv returned (%s)", orig_args->argv[0], strerror(errno)); + fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno)); +} + - static void - clean_up_tmp_files() - { - /* delete intermediate pre-processor file if needed */ - if (i_tmpfile) { - if (!direct_i_file) { - tmp_unlink(i_tmpfile); - } - free(i_tmpfile); - i_tmpfile = NULL; - } - - /* delete the cpp stderr file if necessary */ - if (cpp_stderr) { - tmp_unlink(cpp_stderr); - free(cpp_stderr); - cpp_stderr = NULL; - } - } - +static const char * +temp_dir() +{ + static char *path = NULL; + if (path) return path; /* Memoize */ + path = conf->temporary_dir; + if (str_eq(path, "")) { + path = format("%s/tmp", conf->cache_dir); + } + return path; } + static void + add_pending_tmp_file(const char *path) + { + struct pending_tmp_file *e = x_malloc(sizeof(*e)); + e->path = x_strdup(path); + e->next = pending_tmp_files; + pending_tmp_files = e; + } + + static void + clean_up_pending_tmp_files(void) + { + struct pending_tmp_file *p = pending_tmp_files; + while (p) { + tmp_unlink(p->path); + p = p->next; + /* Leak p->path and p here because clean_up_pending_tmp_files needs to be signal + * safe. */ + } + } + + static void + signal_handler(int signo) + { + (void)signo; + clean_up_pending_tmp_files(); + } + + static void + clean_up_internal_tempdir(void) + { + DIR *dir; + struct dirent *entry; + struct stat st; + time_t now = time(NULL); + - stat(cache_dir, &st); ++ stat(conf->cache_dir, &st); + if (st.st_mtime + 3600 >= now) { + /* No cleanup needed. */ + return; + } + - update_mtime(cache_dir); ++ update_mtime(conf->cache_dir); + - dir = opendir(temp_dir); ++ dir = opendir(temp_dir()); + if (!dir) { + return; + } + + while ((entry = readdir(dir))) { + char *path; + + if (str_eq(entry->d_name, ".") || str_eq(entry->d_name, "..")) { + continue; + } + - path = format("%s/%s", temp_dir, entry->d_name); ++ path = format("%s/%s", temp_dir(), entry->d_name); + if (lstat(path, &st) == 0 && st.st_mtime + 3600 < now) { + tmp_unlink(path); + } + free(path); + } + + closedir(dir); + } + /* * Transform a name to a full path into the cache directory, creating needed * sublevels if needed. Caller frees. @@@ -933,17 -803,9 +987,19 @@@ get_object_name_from_cpp(struct args *a input_base[10] = 0; } - /* now the run */ - path_stderr = format("%s/tmp.cpp_stderr.%s", temp_dir, tmp_string()); + path_stdout = format( + "%s/%s.tmp.%s.%s", + temp_dir(), input_base, tmp_string(), conf->cpp_extension); + path_stderr = format("%s/tmp.cpp_stderr.%s", temp_dir(), tmp_string()); + + if (create_parent_dirs(path_stdout) != 0) { + fatal("Failed to create parent directory for %s: %s\n", + path_stdout, strerror(errno)); + } + ++ add_pending_tmp_file(path_stdout); + add_pending_tmp_file(path_stderr); + time_of_compilation = time(NULL); if (!direct_i_file) { @@@ -1007,10 -866,7 +1057,9 @@@ i_tmpfile = path_stdout; - if (compile_preprocessed_source_code) { + if (conf->run_second_cpp) { - tmp_unlink(path_stderr); + free(path_stderr); + } else { /* * If we are using the CPP trick, we need to remember this * stderr data and output it just before the main stderr from @@@ -2365,115 -1930,6 +2414,115 @@@ out return result; } +static void +create_initial_config_file(struct conf *conf, const char *path) +{ + unsigned max_files; + uint64_t max_size; + char *stats_dir; + FILE *f; + struct stat st; + + if (create_parent_dirs(path) != 0) { + return; + } + + stats_dir = format("%s/0", conf->cache_dir); + if (stat(stats_dir, &st) == 0) { + stats_get_obsolete_limits(stats_dir, &max_files, &max_size); + /* STATS_MAXFILES and STATS_MAXSIZE was stored for each top directory. */ + max_files *= 16; + max_size *= 16; + } else { + max_files = 0; + max_size = conf->max_size; + } + free(stats_dir); + + f = fopen(path, "w"); + if (!f) { + return; + } + if (max_files != 0) { + fprintf(f, "max_files = %u\n", max_files); + conf->max_files = max_files; + } + if (max_size != 0) { + char *size = format_parsable_size_with_suffix(max_size); + fprintf(f, "max_size = %s\n", size); + free(size); + conf->max_size = max_size; + } + fclose(f); +} + +/* + * Read config file(s), populate variables, create configuration file in cache + * directory if missing, etc. + */ +static void +initialize(void) +{ + char *errmsg; + char *p; + struct stat st; + bool should_create_initial_config = false; + + conf_free(conf); + conf = conf_create(); + + p = getenv("CCACHE_CONFIGPATH"); + if (p) { + primary_config_path = x_strdup(p); + } else { + secondary_config_path = format("%s/ccache.conf", TO_STRING(SYSCONFDIR)); + if (!conf_read(conf, secondary_config_path, &errmsg)) { + if (stat(secondary_config_path, &st) == 0) { + fatal("%s", errmsg); + } + /* Missing config file in SYSCONFDIR is OK. */ + free(errmsg); + } + + if ((p = getenv("CCACHE_DIR"))) { + free(conf->cache_dir); + conf->cache_dir = strdup(p); + } + + primary_config_path = format("%s/ccache.conf", conf->cache_dir); + } + + if (!conf_read(conf, primary_config_path, &errmsg)) { + if (stat(primary_config_path, &st) == 0) { + fatal("%s", errmsg); + } + should_create_initial_config = true; + } + + if (!conf_update_from_environment(conf, &errmsg)) { + fatal("%s", errmsg); + } + + if (conf->disable) { + should_create_initial_config = false; + } + + if (should_create_initial_config) { + create_initial_config_file(conf, primary_config_path); + } + + exitfn_init(); + exitfn_add_nullary(stats_flush); - exitfn_add_nullary(clean_up_tmp_files); ++ exitfn_add_nullary(clean_up_pending_tmp_files); + + cc_log("=== CCACHE %s STARTED =========================================", + CCACHE_VERSION); + + if (conf->umask != UINT_MAX) { + umask(conf->umask); + } +} + /* Reset the global state. Used by the test suite. */ void cc_reset(void) @@@ -2556,29 -2041,45 +2605,37 @@@ ccache(int argc, char *argv[] /* Arguments to send to the real compiler. */ struct args *compiler_args; - setup_uncached_err(); - - if (!getenv("CCACHE_READONLY")) { - if (create_cachedirtag(cache_dir) != 0) { - cc_log("failed to create %s/CACHEDIR.TAG (%s)\n", - cache_dir, strerror(errno)); - failed(); - } - } + orig_args = args_init(argc, argv); - sloppiness = parse_sloppiness(getenv("CCACHE_SLOPPINESS")); + initialize(); + find_compiler(argv); - cc_log_argv("Command line: ", argv); - cc_log("Hostname: %s", get_hostname()); - cc_log("Working directory: %s", current_working_dir); ++ signal(SIGHUP, signal_handler); ++ signal(SIGINT, signal_handler); ++ signal(SIGTERM, signal_handler); + - if (base_dir) { - cc_log("Base directory: %s", base_dir); ++ if (str_eq(conf->temporary_dir, "")) { ++ clean_up_internal_tempdir(); + } + - if (getenv("CCACHE_UNIFY")) { - cc_log("Unify mode enabled"); - enable_unify = true; + if (!str_eq(conf->log_file, "")) { + conf_print_items(conf, configuration_logger, NULL); } - if (getenv("CCACHE_NODIRECT") || enable_unify) { - cc_log("Direct mode disabled"); - enable_direct = false; + if (conf->disable) { + cc_log("ccache is disabled"); + failed(); } - if (getenv("CCACHE_COMPRESS")) { - cc_log("Compression enabled"); - enable_compression = true; - } + setup_uncached_err(); - if ((env = getenv("CCACHE_NLEVELS"))) { - nlevels = atoi(env); - if (nlevels < 1) nlevels = 1; - if (nlevels > 8) nlevels = 8; + cc_log_argv("Command line: ", argv); + cc_log("Hostname: %s", get_hostname()); + cc_log("Working directory: %s", current_working_dir); + + if (conf->unify) { + cc_log("Direct mode disabled because unify mode is enabled"); + conf->direct_mode = false; } if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args)) {