diff options
-rw-r--r-- | include/Program.h | 4 | ||||
-rw-r--r-- | src/Program.c | 41 |
2 files changed, 32 insertions, 13 deletions
diff --git a/include/Program.h b/include/Program.h index bc3e91e..cd45b30 100644 --- a/include/Program.h +++ b/include/Program.h @@ -30,7 +30,9 @@ bool wait_program_non_blocking(pid_t process_id, int *status); /* @args need to have at least 2 arguments. The first which is the program name - and the last which is NULL, which indicates end of args + and the last which is NULL, which indicates end of args. + @result_process_id should be set to NULL if you are not interested in the exit status of the child process + and you want the child process to be cleaned up automatically when it dies. */ int exec_program_async(const char **args, pid_t *result_process_id); #if 0 diff --git a/src/Program.c b/src/Program.c index fe2ae3f..bb476c4 100644 --- a/src/Program.c +++ b/src/Program.c @@ -33,12 +33,12 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void } else if(pid == 0) { /* child */ if(prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) { perror("prctl(PR_SET_PDEATHSIG, SIGTERM) failed"); - exit(127); + _exit(127); } /* Test if the parent died before the above call to prctl */ if(getppid() != parent_pid) - exit(127); + _exit(127); dup2(fd[WRITE_END], STDOUT_FILENO); close(fd[READ_END]); @@ -46,7 +46,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void execvp(args[0], args); perror("execvp"); - exit(127); + _exit(127); } else { /* parent */ close(fd[WRITE_END]); @@ -151,16 +151,33 @@ int exec_program_async(const char **args, pid_t *result_process_id) { perror("Failed to fork"); return -err; } else if(pid == 0) { /* child */ - if(prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) { - perror("prctl(PR_SET_PDEATHSIG, SIGTERM) failed"); - exit(127); - } - - /* Test if the parent died before the above call to prctl */ - if(getppid() != parent_pid) - exit(127); + if(result_process_id) { + if(prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) { + perror("prctl(PR_SET_PDEATHSIG, SIGTERM) failed"); + _exit(127); + } - execvp(args[0], args); + /* Test if the parent died before the above call to prctl */ + if(getppid() != parent_pid) + _exit(127); + + execvp(args[0], args); + perror("execvp"); + _exit(127); + } else { + setsid(); + signal(SIGHUP, SIG_IGN); + + // Daemonize child to make the parent the init process which will reap the zombie child + pid_t second_child = fork(); + if(second_child == 0) { // child + execvp(args[0], args); + perror("execvp"); + _exit(127); + } else if(second_child != -1) { + _exit(0); + } + } } else { /* parent */ if(result_process_id) *result_process_id = pid; |