From fa6ec315c83a93ffc7ea4bdf64e0d0527f81a145 Mon Sep 17 00:00:00 2001 From: Asger Gitz-Johansen Date: Thu, 29 Aug 2024 20:51:11 +0200 Subject: [PATCH] feat: unique directory for pipelines Also, start using fork/chdir/exec idiom instead of posix_spawn, because as we all know: posix_spawn is stupid as a system call: https://lwn.net/Articles/360556/ --- include/cli.h | 1 + include/executor.h | 1 + src/cli.c | 15 ++++++++++++--- src/executor.c | 36 +++++++++++++++++++++++++++++------- src/main.c | 2 ++ 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/include/cli.h b/include/cli.h index f3f511c..348dda9 100644 --- a/include/cli.h +++ b/include/cli.h @@ -29,6 +29,7 @@ typedef struct { bool use_colors; optional_str log_file; optional_str pipeline_log_dir; + optional_str pipeline_cwd; optional_strlist environment_vars; } cli_options; diff --git a/include/executor.h b/include/executor.h index c32b8b7..9bc3887 100644 --- a/include/executor.h +++ b/include/executor.h @@ -4,6 +4,7 @@ void executor(void* pipeline_event); void set_logdir(const char* logdir); +void set_working_directory(const char* cwd); void set_shared_environment(const strlist_node* root); #endif diff --git a/src/cli.c b/src/cli.c index 317b936..fe4e010 100644 --- a/src/cli.c +++ b/src/cli.c @@ -51,6 +51,10 @@ cli_options new_options() { result.pipeline_log_dir.has_value = pipeline_log_dir != NULL; result.pipeline_log_dir.value = pipeline_log_dir; + char* pipeline_cwd = getenv("SCI_PIPELINE_CWD"); + result.pipeline_cwd.has_value = pipeline_cwd != NULL; + result.pipeline_cwd.value = pipeline_cwd; + char* environment_vars = getenv("SCI_PIPELINE_ENV_VARS"); if(environment_vars == NULL) { result.environment_vars.has_value = false; @@ -78,17 +82,18 @@ void destroy_options(cli_options v) { } // const char* log_dir = "."; +const char* cwd = "/tmp"; const strlist_node* shared_environment = NULL; void set_shared_environment(const strlist_node* root) { @@ -28,6 +29,13 @@ void set_logdir(const char* logdir) { mkdir(log_dir, 0700); } +void set_working_directory(const char* _cwd) { + cwd = _cwd; + struct stat st = {0}; + if(stat(cwd, &st) == -1) + mkdir(cwd, 0700); +} + char* create_pipeline_id() { uuid_t uuid; uuid_generate(uuid); @@ -98,10 +106,6 @@ void executor(void* data) { // spawn the process pid_t pid; - posix_spawn_file_actions_t actions; - posix_spawn_file_actions_init(&actions); - posix_spawn_file_actions_adddup2(&actions, fd.value, STDOUT_FILENO); - posix_spawn_file_actions_adddup2(&actions, fd.value, STDERR_FILENO); const pipeline_event* const e = data; char** envp = create_environment(e, pipeline_id); int argc; @@ -112,16 +116,34 @@ void executor(void* data) { char arg0[PATH_MAX]; if(which(argv[0], arg0, PATH_MAX) == -1) goto end; - if(posix_spawnp(&pid, arg0, &actions, NULL, argv, envp) != 0) { - perror("posix_spawn"); + + // fork / cwd / exec idiom + pid = fork(); + if(pid < 0) { + perror("fork"); goto end; // I know. The raptors have picked up the scent. I'll just have to mask it with more stinky code. } + + if(pid == 0) { + // child process + dup2(fd.value, STDOUT_FILENO); + dup2(fd.value, STDERR_FILENO); + char* pipeline_cwd = join3(cwd, "/", pipeline_id); + struct stat st = {0}; + if(stat(pipeline_cwd, &st) == -1) + mkdir(pipeline_cwd, 0700); + chdir(pipeline_cwd); + free(pipeline_cwd); + execvpe(arg0, argv, envp); + return; + } + log_info("{%s} (%s) spawned", pipeline_id, e->name); // Wait for process to complete int status; waitpid(pid, &status, 0); - log_info("{%s} (%s) exited with status %d", pipeline_id, e->name, status); + log_info("{%s} (%s) [pid=%d] exited with status %d", pipeline_id, e->name, pid, status); char buf[32]; sprintf(buf, "exited with status %d", status); if(write(fd.value, buf, strnlen(buf, 32)) == -1) diff --git a/src/main.c b/src/main.c index e0b41a6..d69f572 100644 --- a/src/main.c +++ b/src/main.c @@ -101,6 +101,8 @@ int main(int argc, char** argv) { if(args.pipeline_log_dir.has_value) set_logdir(args.pipeline_log_dir.value); + if(args.pipeline_cwd.has_value) + set_working_directory(args.pipeline_cwd.value); struct stat st = {0}; if(stat("/tmp/sci", &st) == -1)