spawn: Allow executing list of handlers 26/206326/3
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Wed, 15 May 2019 12:02:27 +0000 (14:02 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Fri, 17 May 2019 11:39:37 +0000 (13:39 +0200)
This functionality is needed for non-trivial child initialization.

Change-Id: Iac1d5221fc44dc2d65c2acc260e8b9e2b1a01a17

src/crash-manager/crash-manager.c
src/dump_systemstate/dump_systemstate.c
src/dump_systemstate/extras.c
src/log_dump/log_dump.c
src/shared/spawn.c
src/shared/spawn.h

index 9e7bd49..5eb8d6b 100644 (file)
@@ -456,13 +456,14 @@ static void launch_crash_popup(struct crash_info *cinfo)
                        "--cmdpath", cinfo->cmd_path,
                        NULL };
 
-       spawn(av, NULL, spawn_nullstdfds, NULL, NULL, NULL);
+       spawn_param_s param = { .fn = spawn_nullstdfds };
+       spawn(av, NULL, &param, NULL, NULL);
 }
 
 static bool dump_system_state(const struct crash_info *cinfo, pid_t *pid)
 {
        char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-p", "-e", "-f",  cinfo->log_path, NULL};
-       return spawn(av, NULL, NULL, NULL, pid, NULL);
+       return spawn(av, NULL, NULL, pid, NULL);
 }
 
 static void save_so_info(const struct crash_info *cinfo)
@@ -540,7 +541,7 @@ static void launch_dbus_notify(struct crash_info *cinfo)
                        "--prstatus_fd", prstatus_fd_str,
                        NULL };
 
-       spawn(av, NULL, NULL, NULL, NULL, NULL);
+       spawn(av, NULL, NULL, NULL, NULL);
 out:
        free(prstatus_fd_str);
 }
@@ -585,7 +586,7 @@ static bool execute_minicoredump(struct crash_info *cinfo, int *exit_code)
                        NULL
                        };
 
-       is_ok = spawn_wait(args, NULL, NULL, NULL, MINICOREDUMPER_TIMEOUT_MS, exit_code);
+       is_ok = spawn_wait(args, NULL, NULL, MINICOREDUMPER_TIMEOUT_MS, exit_code);
 
        /* Minicoredumper must be executed to dump at least PRSTATUS for
           other tools, coredump, however, might have been disabled. */
@@ -635,8 +636,8 @@ static bool execute_crash_stack(const struct crash_info *cinfo, int *exit_code)
                return false;
        }
 
-       spawn_param_u param = { .int_val = fd };
-       is_ok = spawn_wait(args, NULL, spawn_setstdout, &param, CRASH_STACK_TIMEOUT_MS, exit_code);
+       spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = fd };
+       is_ok = spawn_wait(args, NULL, &param, CRASH_STACK_TIMEOUT_MS, exit_code);
        close(fd);
 
 out:
@@ -913,9 +914,8 @@ static void compress(struct crash_info *cinfo)
        }
 
        char *args[] = {"/bin/zip", "-qyr", zip_path, cinfo->name, NULL};
-
-       spawn_param_u param = { .char_ptr = cinfo->temp_dir };
-       (void)spawn_wait(args, NULL, spawn_chdir, &param, ZIP_TIMEOUT_MS, NULL);
+       spawn_param_s param0 = { .fn = spawn_chdir, .u.char_ptr = cinfo->temp_dir };
+       (void)spawn_wait(args, NULL, &param0, ZIP_TIMEOUT_MS, NULL);
 
        if ((lock_fd = lock_dumpdir()) < 0)
                return;
index b853080..30a8f35 100644 (file)
@@ -170,8 +170,8 @@ int main(int argc, char *argv[])
 #define spawn_wait_checked(av, env) \
        do { \
                int err; \
-               spawn_param_u param = { .int_val = out_fd }; \
-               if (!spawn_wait(av, env, spawn_setstdout, &param, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \
+               spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = out_fd }; \
+               if (!spawn_wait(av, env, &param, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \
                        exit_code |= EXIT_CMDERR; \
                        fprintf_fd(out_fd, "\nCommand failed with error code: %d", err); \
                } \
index 6033485..90625a5 100644 (file)
@@ -97,8 +97,8 @@ int handle_extra_program(int out_fd, struct extra_dump_item *item)
        char *argv[] = {"/bin/sh", "-c", command_line, NULL};
 
        int err;
-       spawn_param_u param = { .int_val = out_fd };
-       bool failed = !spawn_wait(argv, NULL, spawn_setstdout, &param, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0;
+       spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = out_fd };
+       bool failed = !spawn_wait(argv, NULL, &param, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0;
 
        free(command_line);
        return failed ? EXIT_CMDERR : 0;
index aa63f2b..f50bf14 100644 (file)
@@ -185,7 +185,7 @@ static bool dump_scripts(char *const workdir, char *const scriptsdir)
                _D("Calling scriptlet: %s", command);
 
                char *const av[] = {command, workdir, NULL};
-               (void)spawn_wait(av, NULL, NULL, NULL, 0, NULL);
+               (void)spawn_wait(av, NULL, NULL, 0, NULL);
        }
 
        for (i = 0; i < script_num; i++)
@@ -205,7 +205,7 @@ static bool dump_systemstate(const char *const destdir, const char *const timest
        }
 
        char *av[] = {"/usr/bin/dump_systemstate", "-k", "-d", "-j", "-e", "-f", dump_path, NULL};
-       bool is_ok = spawn_wait(av, NULL, NULL, NULL, 0, exit_code);
+       bool is_ok = spawn_wait(av, NULL, NULL, 0, exit_code);
 
        free(dump_path);
 
@@ -223,8 +223,8 @@ static bool compress(char *const destdir, char *const tempdir, char *const versi
 
        _D("compress tempdir is %s", tempdir);
        char *av[] = {"/bin/zip", "-qyr", archive_path, ".", NULL};
-       spawn_param_u param = { .char_ptr = tempdir };
-       bool is_ok = spawn_wait(av, NULL, spawn_chdir, &param, 0, exit_code);
+       spawn_param_s param0 = { .fn = spawn_chdir, .u.char_ptr = tempdir };
+       bool is_ok = spawn_wait(av, NULL, &param0, 0, exit_code);
 
        _I("Storing report at %s", archive_path);
 
index 7139f73..baca45d 100644 (file)
 
 /* spawn prepare function(s) - to be called in child process */
 
-int spawn_setstdout(spawn_param_u *param)
+int spawn_setstdout(spawn_param_s *param)
 {
        assert(param);
-       return dup2(param->int_val, STDOUT_FILENO) < 0 ? -1 : 0;
+       return dup2(param->u.int_val, STDOUT_FILENO) < 0 ? -1 : 0;
 }
 
-int spawn_setstdouterr(spawn_param_u *param)
+int spawn_setstderr(spawn_param_s *param)
 {
        assert(param);
-       return dup2(param->int_val, STDOUT_FILENO) < 0 || dup2(param->int_val, STDERR_FILENO) < 0 ? -1 : 0;
+       return dup2(param->u.int_val, STDERR_FILENO) < 0 ? -1 : 0;
 }
 
-int spawn_nullstdfds(spawn_param_u *param)
+int spawn_nullstdfds(spawn_param_s *param)
 {
        int fd = open("/dev/null", O_RDWR);
        int ret = dup2(fd, STDIN_FILENO) < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0 ? -1 : 0;
@@ -57,16 +57,16 @@ int spawn_nullstdfds(spawn_param_u *param)
        return ret;
 }
 
-int spawn_chdir(spawn_param_u *param)
+int spawn_chdir(spawn_param_s *param)
 {
        assert(param);
-       return chdir(param->char_ptr);
+       return chdir(param->u.char_ptr);
 }
 
-int spawn_umask(spawn_param_u *param)
+int spawn_umask(spawn_param_s *param)
 {
        assert(param);
-       (void)umask(param->mode_t_val);
+       (void)umask(param->u.mode_t_val);
        return 0;
 }
 
@@ -106,19 +106,25 @@ bool wait_for_pid(pid_t pid, int *exit_code)
        return true;
 }
 
-static int spawn_child(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param)
+static int spawn_child(char *const av[], char *const ev[], spawn_param_s *param)
 {
        static const int spawn_error = 127;
 
-       int r = prep ? prep(param) : 0;
-       if (r < 0)
-               return spawn_error;
+       while (param) {
+               assert(param->fn);
+
+               int r = param->fn(param);
+               if (r < 0)
+                       return spawn_error;
+
+               param = param->next;
+       };
 
        execve(av[0], av, ev);
        return spawn_error;
 }
 
-bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, pid_t *childpid, int *childfd)
+bool spawn(char *const av[], char *const ev[], spawn_param_s *param, pid_t *childpid, int *childfd)
 {
        int pipefd[2];
        if (pipe(pipefd) < 0) {
@@ -134,7 +140,7 @@ bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_para
                return false;
        } else if (pid == 0) {
                close(pipefd[0]);
-               _exit(spawn_child(av, ev, prep, param));
+               _exit(spawn_child(av, ev, param));
        }
        close(pipefd[1]);
 
@@ -180,12 +186,12 @@ static bool wait_and_kill(pid_t childpid, int childfd, int timeout_ms)
        return true;
 }
 
-bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, int timeout_ms, int *exit_code)
+bool spawn_wait(char *const av[], char *const ev[], spawn_param_s *param, int timeout_ms, int *exit_code)
 {
        pid_t childpid;
        int childfd;
 
-       if (!spawn(av, ev, prep, param, &childpid, &childfd)) {
+       if (!spawn(av, ev, param, &childpid, &childfd)) {
                _E("spawn() returned an error - aborting waiting");
                return false;
        }
index 7177ae8..431b173 100644 (file)
@@ -26,23 +26,30 @@ extern "C" {
 
 #define DEFAULT_COMMAND_TIMEOUT_MS (60*1000) /* 60sec */
 
-typedef union {
-       int int_val;
-       mode_t mode_t_val;
-       char *char_ptr;
-} spawn_param_u;
+struct spawn_param;
 
-typedef int (*spawn_prepare_fn)(spawn_param_u *param);
+typedef int (*spawn_prepare_fn)(struct spawn_param *param);
 
-int spawn_setstdout(spawn_param_u *param);
-int spawn_setstdouterr(spawn_param_u *param);
-int spawn_nullstdfds(spawn_param_u *param);
-int spawn_chdir(spawn_param_u *param);
-int spawn_umask(spawn_param_u *param);
+typedef struct spawn_param {
+       spawn_prepare_fn fn;
+
+       struct spawn_param *next;
+       union {
+               int int_val;
+               mode_t mode_t_val;
+               char *char_ptr;
+       } u;
+} spawn_param_s;
+
+int spawn_setstdout(spawn_param_s *param);
+int spawn_setstderr(spawn_param_s *param);
+int spawn_nullstdfds(spawn_param_s *param);
+int spawn_chdir(spawn_param_s *param);
+int spawn_umask(spawn_param_s *param);
 
 bool wait_for_pid(pid_t pid, int *exit_code);
-bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, pid_t *childpid, int *childfd);
-bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, int timeout_ms, int *exit_code);
+bool spawn(char *const av[], char *const ev[], spawn_param_s *param, pid_t *childpid, int *childfd);
+bool spawn_wait(char *const av[], char *const ev[], spawn_param_s *param, int timeout_ms, int *exit_code);
 
 #ifdef __cplusplus
 }