chiark / gitweb /
Simplify execute_directory()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 8 Jan 2015 22:30:07 +0000 (17:30 -0500)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 11 Jan 2015 23:17:33 +0000 (18:17 -0500)
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.

src/core/manager.c
src/core/shutdown.c
src/shared/util.c
src/shared/util.h
src/sleep/sleep.c
src/test/test-util.c

index c18312a..4918091 100644 (file)
@@ -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);
index 6492b19..4cbdf12 100644 (file)
@@ -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) {
index 7d753e4..06bd1b9 100644 (file)
@@ -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);
index 3b3035a..3d31cb3 100644 (file)
@@ -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);
 
index 56b963a..2fb5f0c 100644 (file)
@@ -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;
 }
index d529a21..d862149 100644 (file)
@@ -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);