summaryrefslogtreecommitdiffstats
path: root/src/fastd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fastd.c')
-rw-r--r--src/fastd.c91
1 files changed, 27 insertions, 64 deletions
diff --git a/src/fastd.c b/src/fastd.c
index 2b08a7e..5ce4ced 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -501,92 +501,55 @@ static void drop_caps(void) {
/* will double fork and forward potential exit codes from the child to the parent */
static int daemonize(void) {
- static const uint8_t ERROR_STATUS = 1;
-
uint8_t status = 1;
- int parent_rpipe, parent_wpipe;
- fastd_open_pipe(&parent_rpipe, &parent_wpipe);
+ int pipefd[2];
+
+ if (pipe(pipefd))
+ exit_errno("pipe");
+
+ fastd_setfd(pipefd[0], FD_CLOEXEC, 0);
+ fastd_setfd(pipefd[1], FD_CLOEXEC, 0);
pid_t fork1 = fork();
if (fork1 < 0) {
exit_errno("fork");
}
- else if (fork1 == 0) {
+ else if (fork1 > 0) {
+ /* parent */
+ if (close(pipefd[1]) < 0)
+ exit_errno("close");
+
+ if (waitpid(fork1, NULL, 0) < 0)
+ exit_errno("waitpid");
+
+ if (read(pipefd[0], &status, 1) < 0)
+ exit_errno("read");
+
+ exit(status);
+ }
+ else {
/* child 1 */
- if (close(parent_rpipe) < 0)
+ if (close(pipefd[0]) < 0)
pr_error_errno("close");
if (setsid() < 0)
pr_error_errno("setsid");
- int child_rpipe, child_wpipe;
- fastd_open_pipe(&child_rpipe, &child_wpipe);
-
pid_t fork2 = fork();
if (fork2 < 0) {
- write(parent_wpipe, &ERROR_STATUS, 1);
exit_errno("fork");
}
- else if (fork2 == 0) {
- /* child 2 */
-
- if (close(child_rpipe) < 0 || close(parent_wpipe) < 0) {
- write(child_wpipe, &ERROR_STATUS, 1);
- pr_error_errno("close");
- }
-
- return child_wpipe;
+ else if (fork2 > 0) {
+ /* still child 1 */
+ _exit(0);
}
else {
- /* still child 1 */
- int child_status;
- pid_t ret;
- do {
- if (read(child_rpipe, &status, 1) > 0) {
- write(parent_wpipe, &status, 1);
- exit(0);
- }
-
- ret = waitpid(fork2, &child_status, WNOHANG);
- } while (!ret);
-
- if (ret < 0) {
- write(child_wpipe, &ERROR_STATUS, 1);
- pr_error_errno("waitpid");
- }
-
- if (WIFEXITED(child_status)) {
- status = WEXITSTATUS(child_status);
- write(parent_wpipe, &status, 1);
- exit(status);
- }
- else {
- write(parent_wpipe, &ERROR_STATUS, 1);
- if (WIFSIGNALED(child_status))
- exit_error("child exited with signal %i", WTERMSIG(child_status));
- exit(1);
- }
+ /* child 2 */
+ return pipefd[1];
}
}
- else {
- /* parent */
- struct sigaction action;
- action.sa_flags = 0;
- sigemptyset(&action.sa_mask);
- action.sa_handler = SIG_IGN;
-
- if (sigaction(SIGCHLD, &action, NULL))
- exit_errno("sigaction");
-
- if (read(parent_rpipe, &status, 1) < 0)
- exit_errno("read");
-
- exit(status);
- }
-
- return -1;
}
#ifdef USE_SYSTEMD