This functionality is needed for non-trivial child initialization.
Change-Id: Iac1d5221fc44dc2d65c2acc260e8b9e2b1a01a17
"--cmdpath", cinfo->cmd_path,
NULL };
- spawn(av, NULL, spawn_nullstdfds, NULL, NULL, NULL);
+ spawn_param_s param = { .fn = spawn_nullstdfds };
+ spawn(av, NULL, ¶m, 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)
"--prstatus_fd", prstatus_fd_str,
NULL };
- spawn(av, NULL, NULL, NULL, NULL, NULL);
+ spawn(av, NULL, NULL, NULL, NULL);
out:
free(prstatus_fd_str);
}
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. */
return false;
}
- spawn_param_u param = { .int_val = fd };
- is_ok = spawn_wait(args, NULL, spawn_setstdout, ¶m, CRASH_STACK_TIMEOUT_MS, exit_code);
+ spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = fd };
+ is_ok = spawn_wait(args, NULL, ¶m, CRASH_STACK_TIMEOUT_MS, exit_code);
close(fd);
out:
}
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, ¶m, ZIP_TIMEOUT_MS, NULL);
+ spawn_param_s param0 = { .fn = spawn_chdir, .u.char_ptr = cinfo->temp_dir };
+ (void)spawn_wait(args, NULL, ¶m0, ZIP_TIMEOUT_MS, NULL);
if ((lock_fd = lock_dumpdir()) < 0)
return;
#define spawn_wait_checked(av, env) \
do { \
int err; \
- spawn_param_u param = { .int_val = out_fd }; \
- if (!spawn_wait(av, env, spawn_setstdout, ¶m, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \
+ spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = out_fd }; \
+ if (!spawn_wait(av, env, ¶m, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \
exit_code |= EXIT_CMDERR; \
fprintf_fd(out_fd, "\nCommand failed with error code: %d", err); \
} \
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, ¶m, 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, ¶m, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0;
free(command_line);
return failed ? EXIT_CMDERR : 0;
_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++)
}
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);
_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, ¶m, 0, exit_code);
+ spawn_param_s param0 = { .fn = spawn_chdir, .u.char_ptr = tempdir };
+ bool is_ok = spawn_wait(av, NULL, ¶m0, 0, exit_code);
_I("Storing report at %s", archive_path);
/* 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;
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;
}
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) {
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]);
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;
}
#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
}