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/
This commit is contained in:
parent
22075e17e1
commit
fa6ec315c8
@ -29,6 +29,7 @@ typedef struct {
|
|||||||
bool use_colors;
|
bool use_colors;
|
||||||
optional_str log_file;
|
optional_str log_file;
|
||||||
optional_str pipeline_log_dir;
|
optional_str pipeline_log_dir;
|
||||||
|
optional_str pipeline_cwd;
|
||||||
optional_strlist environment_vars;
|
optional_strlist environment_vars;
|
||||||
} cli_options;
|
} cli_options;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
void executor(void* pipeline_event);
|
void executor(void* pipeline_event);
|
||||||
void set_logdir(const char* logdir);
|
void set_logdir(const char* logdir);
|
||||||
|
void set_working_directory(const char* cwd);
|
||||||
void set_shared_environment(const strlist_node* root);
|
void set_shared_environment(const strlist_node* root);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
15
src/cli.c
15
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.has_value = pipeline_log_dir != NULL;
|
||||||
result.pipeline_log_dir.value = pipeline_log_dir;
|
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");
|
char* environment_vars = getenv("SCI_PIPELINE_ENV_VARS");
|
||||||
if(environment_vars == NULL) {
|
if(environment_vars == NULL) {
|
||||||
result.environment_vars.has_value = false;
|
result.environment_vars.has_value = false;
|
||||||
@ -78,17 +82,18 @@ void destroy_options(cli_options v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// <max
|
// <max
|
||||||
const char* optstring = "f:L:w:v:Cl:e:hV";
|
const char* optstring = "f:L:P:w:v:Cl:e:hV";
|
||||||
const char* help_msg =
|
const char* help_msg =
|
||||||
"%s %s\n"
|
"%s %s\n"
|
||||||
"Usage: [-f file] [-L dir] [-w count] [-v level] \n"
|
"Usage: [-f file] [-L dir] [-P dir] [-w count]\n\n"
|
||||||
" [-C] [-l file] [-e ENV] [-h] [-V]\n"
|
" [-v level] [-C] [-l file] [-e ENV] [-h] [-V]\n"
|
||||||
"\n"
|
"\n"
|
||||||
SCI_DESCRIPTION "\n"
|
SCI_DESCRIPTION "\n"
|
||||||
"\n"
|
"\n"
|
||||||
"OPTIONS:\n"
|
"OPTIONS:\n"
|
||||||
" -f file Set sci config file\n"
|
" -f file Set sci config file\n"
|
||||||
" -L dir Set pipeline log output directory\n"
|
" -L dir Set pipeline log output directory\n"
|
||||||
|
" -P dir Set pipeline working directory prefix\n"
|
||||||
" -w count Set the amount of worker threads\n"
|
" -w count Set the amount of worker threads\n"
|
||||||
" -v level Set verbosity level [0-4]\n"
|
" -v level Set verbosity level [0-4]\n"
|
||||||
" -C Force color output, ignoring $NO_COLOR\n"
|
" -C Force color output, ignoring $NO_COLOR\n"
|
||||||
@ -119,6 +124,10 @@ cli_options parse(int argc, char** argv) {
|
|||||||
options.pipeline_log_dir.value = strdup(optarg);
|
options.pipeline_log_dir.value = strdup(optarg);
|
||||||
options.pipeline_log_dir.has_value = true;
|
options.pipeline_log_dir.has_value = true;
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
options.pipeline_cwd.value = strdup(optarg);
|
||||||
|
options.pipeline_cwd.has_value = true;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
options.verbosity = atoi(optarg);
|
options.verbosity = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
const char* log_dir = ".";
|
const char* log_dir = ".";
|
||||||
|
const char* cwd = "/tmp";
|
||||||
const strlist_node* shared_environment = NULL;
|
const strlist_node* shared_environment = NULL;
|
||||||
|
|
||||||
void set_shared_environment(const strlist_node* root) {
|
void set_shared_environment(const strlist_node* root) {
|
||||||
@ -28,6 +29,13 @@ void set_logdir(const char* logdir) {
|
|||||||
mkdir(log_dir, 0700);
|
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() {
|
char* create_pipeline_id() {
|
||||||
uuid_t uuid;
|
uuid_t uuid;
|
||||||
uuid_generate(uuid);
|
uuid_generate(uuid);
|
||||||
@ -98,10 +106,6 @@ void executor(void* data) {
|
|||||||
|
|
||||||
// spawn the process
|
// spawn the process
|
||||||
pid_t pid;
|
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;
|
const pipeline_event* const e = data;
|
||||||
char** envp = create_environment(e, pipeline_id);
|
char** envp = create_environment(e, pipeline_id);
|
||||||
int argc;
|
int argc;
|
||||||
@ -112,16 +116,34 @@ void executor(void* data) {
|
|||||||
char arg0[PATH_MAX];
|
char arg0[PATH_MAX];
|
||||||
if(which(argv[0], arg0, PATH_MAX) == -1)
|
if(which(argv[0], arg0, PATH_MAX) == -1)
|
||||||
goto end;
|
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.
|
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);
|
log_info("{%s} (%s) spawned", pipeline_id, e->name);
|
||||||
|
|
||||||
// Wait for process to complete
|
// Wait for process to complete
|
||||||
int status;
|
int status;
|
||||||
waitpid(pid, &status, 0);
|
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];
|
char buf[32];
|
||||||
sprintf(buf, "exited with status %d", status);
|
sprintf(buf, "exited with status %d", status);
|
||||||
if(write(fd.value, buf, strnlen(buf, 32)) == -1)
|
if(write(fd.value, buf, strnlen(buf, 32)) == -1)
|
||||||
|
@ -101,6 +101,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if(args.pipeline_log_dir.has_value)
|
if(args.pipeline_log_dir.has_value)
|
||||||
set_logdir(args.pipeline_log_dir.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};
|
struct stat st = {0};
|
||||||
if(stat("/tmp/sci", &st) == -1)
|
if(stat("/tmp/sci", &st) == -1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user