aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hubbs <w.d.hubbs@gmail.com>2019-02-25 17:32:12 -0600
committerWilliam Hubbs <w.d.hubbs@gmail.com>2019-02-25 18:55:13 -0600
commit0d378974bfbd69c5427d44c0a43a9f36389aa235 (patch)
tree4b9465c29a28ad51d321f503da626e7790e18fbd
parent028da5c2e37d81d4e242a546eb48a20eafe0cc56 (diff)
openrc-init: fix waitpid checks
The do_openrc() function was not waiting properly for the child process which started the runlevel to return. We need to repeatedly call waitpid() until its return value matches the pid of the child process or the child process does not exist. This fixes #216. This fixes #300.
-rw-r--r--src/rc/openrc-init.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/src/rc/openrc-init.c b/src/rc/openrc-init.c
index e1aaeaee..957d5147 100644
--- a/src/rc/openrc-init.c
+++ b/src/rc/openrc-init.c
@@ -43,40 +43,45 @@
static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin";
static const char *rc_default_runlevel = "default";
-static pid_t do_openrc(const char *runlevel)
+static void do_openrc(const char *runlevel)
{
pid_t pid;
- sigset_t signals;
+ sigset_t all_signals;
+ sigset_t our_signals;
+ sigfillset(&all_signals);
+ /* block all signals */
+ sigprocmask(SIG_BLOCK, &all_signals, &our_signals);
pid = fork();
switch (pid) {
case -1:
perror("fork");
+ exit(1);
break;
case 0:
setsid();
/* unblock all signals */
- sigemptyset(&signals);
- sigprocmask(SIG_SETMASK, &signals, NULL);
+ sigprocmask(SIG_UNBLOCK, &all_signals, NULL);
printf("Starting %s runlevel\n", runlevel);
execlp("openrc", "openrc", runlevel, NULL);
perror("exec");
+ exit(1);
break;
default:
+ /* restore our signal mask */
+ sigprocmask(SIG_SETMASK, &our_signals, NULL);
+ while (waitpid(pid, NULL, 0) != pid)
+ if (errno == ECHILD)
+ break;
break;
}
- return pid;
}
static void init(const char *default_runlevel)
{
const char *runlevel = NULL;
- pid_t pid;
-
- pid = do_openrc("sysinit");
- waitpid(pid, NULL, 0);
- pid = do_openrc("boot");
- waitpid(pid, NULL, 0);
+ do_openrc("sysinit");
+ do_openrc("boot");
if (default_runlevel)
runlevel = default_runlevel;
else
@@ -87,8 +92,7 @@ static void init(const char *default_runlevel)
printf("%s is an invalid runlevel\n", runlevel);
runlevel = rc_default_runlevel;
}
- pid = do_openrc(runlevel);
- waitpid(pid, NULL, 0);
+ do_openrc(runlevel);
log_wtmp("reboot", "~~", 0, RUN_LVL, "~~");
}
@@ -100,11 +104,9 @@ static void handle_reexec(char *my_name)
static void handle_shutdown(const char *runlevel, int cmd)
{
- pid_t pid;
struct timespec ts;
- pid = do_openrc(runlevel);
- while (waitpid(pid, NULL, 0) != pid);
+ do_openrc(runlevel);
printf("Sending the final term signal\n");
kill(-1, SIGTERM);
ts.tv_sec = 3;
@@ -118,10 +120,7 @@ static void handle_shutdown(const char *runlevel, int cmd)
static void handle_single(void)
{
- pid_t pid;
-
- pid = do_openrc("single");
- while (waitpid(pid, NULL, 0) != pid);
+ do_openrc("single");
}
static void reap_zombies(void)