diff --git a/include/villas/nodes/shmem.h b/include/villas/nodes/shmem.h index 5bf02ec96..0ea273dc3 100644 --- a/include/villas/nodes/shmem.h +++ b/include/villas/nodes/shmem.h @@ -15,6 +15,7 @@ struct shmem { int insize, outsize; /**< Size of ingoing and outgoing queue, respectively. */ int cond_out; /**< Whether to use a pthread_cond_t to signal if new samples are written to outqueue. */ int cond_in; /**< Whether to use a pthread_cond_t to signal if new samples are written to inqueue. */ + char **exec; /**< External program to execute on start. */ struct memtype *manager; /**< Manager for the shared memory region. */ int fd; /**< Handle as returned by shm_open().*/ diff --git a/include/villas/utils.h b/include/villas/utils.h index 99fbf4bfb..856c4ec1c 100644 --- a/include/villas/utils.h +++ b/include/villas/utils.h @@ -245,3 +245,5 @@ void signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx)); * @retval 0 Everything was okay. */ int sha1sum(FILE *f, unsigned char *sha1); + +pid_t spawn(const char* name, char **argv); diff --git a/lib/nodes/shmem.c b/lib/nodes/shmem.c index 0c890b6d6..e2f5435c3 100644 --- a/lib/nodes/shmem.c +++ b/lib/nodes/shmem.c @@ -28,6 +28,22 @@ int shmem_parse(struct node *n, config_setting_t *cfg) { shm->cond_out = false; if (!config_setting_lookup_bool(cfg, "cond_in", &shm->cond_in)) shm->cond_in = false; + config_setting_t *exec_setting = config_setting_lookup(cfg, "exec"); + if (!exec_setting) { + shm->exec = NULL; + } else { + if (!config_setting_is_array(exec_setting)) + cerror(exec_setting, "Invalid format for exec"); + shm->exec = malloc(sizeof(char*) * (config_setting_length(exec_setting) + 1)); + int i; + for (i = 0; i < config_setting_length(exec_setting); i++) { + const char* elm = config_setting_get_string_elem(exec_setting, i); + if (!elm) + cerror(exec_setting, "Invalid format for exec"); + shm->exec[i] = strdup(elm); + } + shm->exec[i] = NULL; + } return 0; } @@ -73,6 +89,8 @@ int shmem_open(struct node *n) { if (pool_init(&shm->shared->pool, shm->insize+shm->outsize, SAMPLE_LEN(shm->sample_size), shm->manager) < 0) error("Shm pool allocation failed (not enough memory?)"); + if (shm->exec && !spawn(shm->exec[0], shm->exec)) + serror("Failed to spawn external program"); return 0; } diff --git a/lib/utils.c b/lib/utils.c index 4b408d940..9f3b3edbe 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -411,6 +411,11 @@ void signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx)) sigemptyset(&sa_quit.sa_mask); sigaction(SIGINT, &sa_quit, NULL); sigaction(SIGTERM, &sa_quit, NULL); + struct sigaction sa_chld = { + .sa_flags = 0, + .sa_handler = SIG_IGN + }; + sigaction(SIGCHLD, &sa_chld, NULL); } int sha1sum(FILE *f, unsigned char *sha1) @@ -436,4 +441,17 @@ int sha1sum(FILE *f, unsigned char *sha1) fseek(f, seek, SEEK_SET); return 0; -} \ No newline at end of file +} + +pid_t +spawn(const char* name, char **argv) { + pid_t pid = fork(); + switch(pid) { + case -1: + return -1; + case 0: + return execvp(name, argv); + default: + return pid; + } +}