From: Zbigniew Jędrzejewski-Szmek Date: Thu, 8 Jan 2015 22:30:07 +0000 (-0500) Subject: Simplify execute_directory() X-Git-Tag: v219~570 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=4968105790c65af58d4ab42bffa2a4bedc0be8ee Simplify execute_directory() Remove the optional sepearate opening of the directory, it would be just too complicated with the change to multiple directories. Move the middle of execute_directory() to a seperate function to make it easier to grok. --- diff --git a/src/core/manager.c b/src/core/manager.c index c18312a36..491809112 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2776,7 +2776,6 @@ static void trim_generator_dir(Manager *m, char **generator) { } void manager_run_generators(Manager *m) { - _cleanup_closedir_ DIR *d = NULL; const char *generator_path; const char *argv[5]; int r; @@ -2787,13 +2786,13 @@ void manager_run_generators(Manager *m) { return; generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH; - d = opendir(generator_path); - if (!d) { - if (errno == ENOENT) - return; - log_error_errno(errno, "Failed to enumerate generator directory %s: %m", - generator_path); + /* Optimize by skipping the whole process by not creating output directories + * if no generators are found. */ + if (access(generator_path, F_OK) != 0) { + if (errno != ENOENT) + log_error_errno(errno, "Failed to open generator directory %s: %m", + generator_path); return; } @@ -2816,7 +2815,7 @@ void manager_run_generators(Manager *m) { argv[4] = NULL; RUN_WITH_UMASK(0022) - execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv); + execute_directory(generator_path, DEFAULT_TIMEOUT_USEC, (char**) argv); finish: trim_generator_dir(m, &m->generator_unit_path); diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 6492b1977..4cbdf1258 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -308,7 +308,7 @@ int main(int argc, char *argv[]) { arguments[0] = NULL; arguments[1] = arg_verb; arguments[2] = NULL; - execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); + execute_directory(SYSTEM_SHUTDOWN_PATH, DEFAULT_TIMEOUT_USEC, arguments); if (!in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0) { diff --git a/src/shared/util.c b/src/shared/util.c index 7d753e448..06bd1b9f0 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -4037,117 +4037,112 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { return endswith(de->d_name, suffix); } -void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) { - pid_t executor_pid; - int r; +static int do_execute(const char *directory, usec_t timeout, char *argv[]) { + _cleanup_hashmap_free_free_ Hashmap *pids = NULL; + _cleanup_closedir_ DIR *d; + struct dirent *de; - assert(directory); + /* We fork this all off from a child process so that we can + * somewhat cleanly make use of SIGALRM to set a time limit */ - /* Executes all binaries in a directory in parallel and waits - * for them to finish. Optionally a timeout is applied. */ + reset_all_signal_handlers(); + reset_signal_mask(); - executor_pid = fork(); - if (executor_pid < 0) { - log_error_errno(errno, "Failed to fork: %m"); - return; + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - } else if (executor_pid == 0) { - _cleanup_hashmap_free_free_ Hashmap *pids = NULL; - _cleanup_closedir_ DIR *_d = NULL; - struct dirent *de; + d = opendir(directory); + if (!d) { + if (errno == ENOENT) + return 0; - /* We fork this all off from a child process so that - * we can somewhat cleanly make use of SIGALRM to set - * a time limit */ + return log_error_errno(errno, "Failed to open directory %s: %m", directory); + } - reset_all_signal_handlers(); - reset_signal_mask(); + pids = hashmap_new(NULL); + if (!pids) + return log_oom(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + FOREACH_DIRENT(de, d, break) { + _cleanup_free_ char *path = NULL; + pid_t pid; + int r; - if (!d) { - d = _d = opendir(directory); - if (!d) { - if (errno == ENOENT) - _exit(EXIT_SUCCESS); + if (!dirent_is_file(de)) + continue; - log_error_errno(errno, "Failed to enumerate directory %s: %m", directory); - _exit(EXIT_FAILURE); - } - } + path = strjoin(directory, "/", de->d_name, NULL); + if (!path) + return log_oom(); - pids = hashmap_new(NULL); - if (!pids) { - log_oom(); - _exit(EXIT_FAILURE); - } + pid = fork(); + if (pid < 0) { + log_error_errno(errno, "Failed to fork: %m"); + continue; + } else if (pid == 0) { + char *_argv[2]; - FOREACH_DIRENT(de, d, break) { - _cleanup_free_ char *path = NULL; - pid_t pid; + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - if (!dirent_is_file(de)) - continue; + if (!argv) { + _argv[0] = path; + _argv[1] = NULL; + argv = _argv; + } else + argv[0] = path; - path = strjoin(directory, "/", de->d_name, NULL); - if (!path) { - log_oom(); - _exit(EXIT_FAILURE); - } + execv(path, argv); + return log_error_errno(errno, "Failed to execute %s: %m", path); + } - pid = fork(); - if (pid < 0) { - log_error_errno(errno, "Failed to fork: %m"); - continue; - } else if (pid == 0) { - char *_argv[2]; + log_debug("Spawned %s as " PID_FMT ".", path, pid); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + r = hashmap_put(pids, UINT_TO_PTR(pid), path); + if (r < 0) + return log_oom(); - if (!argv) { - _argv[0] = path; - _argv[1] = NULL; - argv = _argv; - } else - argv[0] = path; + path = NULL; + } - execv(path, argv); - log_error_errno(errno, "Failed to execute %s: %m", path); - _exit(EXIT_FAILURE); - } + /* Abort execution of this process after the timout. We simply + * rely on SIGALRM as default action terminating the process, + * and turn on alarm(). */ - log_debug("Spawned %s as " PID_FMT ".", path, pid); + if (timeout != USEC_INFINITY) + alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); - r = hashmap_put(pids, UINT_TO_PTR(pid), path); - if (r < 0) { - log_oom(); - _exit(EXIT_FAILURE); - } + while (!hashmap_isempty(pids)) { + _cleanup_free_ char *path = NULL; + pid_t pid; - path = NULL; - } + pid = PTR_TO_UINT(hashmap_first_key(pids)); + assert(pid > 0); + + path = hashmap_remove(pids, UINT_TO_PTR(pid)); + assert(path); - /* Abort execution of this process after the - * timout. We simply rely on SIGALRM as default action - * terminating the process, and turn on alarm(). */ + wait_for_terminate_and_warn(path, pid, true); + } - if (timeout != USEC_INFINITY) - alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); + return 0; +} - while (!hashmap_isempty(pids)) { - _cleanup_free_ char *path = NULL; - pid_t pid; +void execute_directory(const char *directory, usec_t timeout, char *argv[]) { + pid_t executor_pid; + int r; - pid = PTR_TO_UINT(hashmap_first_key(pids)); - assert(pid > 0); + assert(directory); - path = hashmap_remove(pids, UINT_TO_PTR(pid)); - assert(path); + /* Executes all binaries in the directory in parallel and waits + * for them to finish. Optionally a timeout is applied. */ - wait_for_terminate_and_warn(path, pid, true); - } + executor_pid = fork(); + if (executor_pid < 0) { + log_error_errno(errno, "Failed to fork: %m"); + return; - _exit(EXIT_SUCCESS); + } else if (executor_pid == 0) { + r = do_execute(directory, timeout, argv); + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } wait_for_terminate_and_warn(directory, executor_pid, true); diff --git a/src/shared/util.h b/src/shared/util.h index 3b3035a1c..3d31cb3f0 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -534,7 +534,7 @@ bool tty_is_console(const char *tty) _pure_; int vtnr_from_tty(const char *tty); const char *default_term_for_tty(const char *tty); -void execute_directory(const char *directory, DIR *_d, usec_t timeout, char *argv[]); +void execute_directory(const char *directory, usec_t timeout, char *argv[]); int kill_and_sigcont(pid_t pid, int sig); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 56b963a72..2fb5f0c8e 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -107,7 +107,7 @@ static int execute(char **modes, char **states) { if (r < 0) return r; - execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); + execute_directory(SYSTEM_SLEEP_PATH, DEFAULT_TIMEOUT_USEC, arguments); log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), @@ -126,7 +126,7 @@ static int execute(char **modes, char **states) { NULL); arguments[1] = (char*) "post"; - execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); + execute_directory(SYSTEM_SLEEP_PATH, DEFAULT_TIMEOUT_USEC, arguments); return r; } diff --git a/src/test/test-util.c b/src/test/test-util.c index d529a213c..d862149fa 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -1219,7 +1219,7 @@ static void test_execute_directory(void) { assert_se(chmod(name2, 0755) == 0); assert_se(touch(name3) >= 0); - execute_directory(tempdir, NULL, DEFAULT_TIMEOUT_USEC, NULL); + execute_directory(tempdir, DEFAULT_TIMEOUT_USEC, NULL); assert_se(access("/tmp/test-execute_directory/it_works", F_OK) >= 0); assert_se(access("/tmp/test-execute_directory/it_works2", F_OK) >= 0);