diff options
author | Roy Marples <roy@marples.name> | 2008-04-28 16:04:16 +0000 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2008-04-28 16:04:16 +0000 |
commit | 53902cefb8a62601fd43e33ba91965b19a239ac0 (patch) | |
tree | e476d9918f68f91da9c50799c38fd5fbfe93956c | |
parent | 75f991068d9bc5830a973817c0eb5ef4b978ff14 (diff) |
Add rc_program function which uses fork and signal masking to try and resolve the waitpid issue, Gentoo #219179.
-rw-r--r-- | src/rc/rc.c | 93 |
1 files changed, 40 insertions, 53 deletions
diff --git a/src/rc/rc.c b/src/rc/rc.c index 91fe8393..35e0bdd9 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -277,33 +277,12 @@ static void mark_interactive(void) fclose(fp); } -static void sulogin(bool cont) +static void run_program(const char *prog) { struct sigaction sa; sigset_t full; sigset_t old; pid_t pid; -#ifdef __linux__ - const char *sys = rc_sys(); - - /* VSERVER and OPENVZ systems cannot do a sulogin */ - if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) { - execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); - eerrorx("%s: unable to exec `/sbin/halt': %s", - applet, strerror(errno)); - } -#endif - - if (! cont) { - rc_logger_close(); -#ifdef __linux__ - execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL); - eerrorx("%s: unable to exec `/sbin/sulogin': %s", - applet, strerror(errno)); -#else - exit(EXIT_SUCCESS); -#endif - } /* We need to block signals until we have forked */ memset(&sa, 0, sizeof(sa)); @@ -311,7 +290,7 @@ static void sulogin(bool cont) sigemptyset(&sa.sa_mask); sigfillset(&full); sigprocmask(SIG_SETMASK, &full, &old); - pid = vfork(); + pid = fork(); if (pid == -1) eerrorx("%s: fork: %s", applet, strerror(errno)); @@ -331,21 +310,47 @@ static void sulogin(bool cont) if (termios_orig) tcsetattr(fileno(stdin), TCSANOW, termios_orig); -#ifdef __linux__ - execl(SULOGIN, SULOGIN, (char *) NULL); - eerror("%s: unable to exec `%s': %s", applet, SULOGIN, + execl(prog, prog, (char *) NULL); + eerror("%s: unable to exec `%s': %s", applet, prog, strerror(errno)); -#else - execl("/bin/sh", "/bin/sh", (char *) NULL); - eerror("%s: unable to exec `/bin/sh': %s", applet, - strerror(errno)); -#endif _exit(EXIT_FAILURE); } /* Unmask signals and wait for child */ sigprocmask(SIG_SETMASK, &old, NULL); - rc_waitpid(pid); + if (rc_waitpid(pid) == -1) + eerrorx("%s: failed to exec `%s'", applet, prog); +} + +static void sulogin(bool cont) +{ +#ifdef __linux__ + const char *sys = rc_sys(); + + /* VSERVER and OPENVZ systems cannot do a sulogin */ + if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) { + execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/halt': %s", + applet, strerror(errno)); + } +#endif + + if (! cont) { + rc_logger_close(); +#ifdef __linux__ + execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/sulogin': %s", + applet, strerror(errno)); +#else + exit(EXIT_SUCCESS); +#endif + } + +#ifdef __linux__ + run_program(SULOGIN); +#else + run_program("/bin/sh"); +#endif } static void single_user(void) @@ -510,23 +515,6 @@ static void handle_signal(int sig) errno = serrno; } -static void run_script(const char *script) -{ - pid_t pid = vfork(); - - if (pid < 0) - eerrorx("%s: vfork: %s", applet, strerror(errno)); - else if (pid == 0) { - execl(script, script, (char *) NULL); - eerror("%s: unable to exec `%s': %s", - script, applet, strerror(errno)); - _exit(EXIT_FAILURE); - } - - if (rc_waitpid(pid) != 0) - eerrorx("%s: failed to exec `%s'", applet, script); -} - static void do_coldplug(void) { size_t l; @@ -651,7 +639,7 @@ static void do_newlevel(const char *newlevel) * This should just setup the console to use the correct * font. Maybe it should setup the keyboard too? */ if (exists(INITEARLYSH)) - run_script(INITEARLYSH); + run_program(INITEARLYSH); uname(&uts); printf("\n %sOpenRC %s" VERSION "%s is starting up %s", @@ -679,7 +667,7 @@ static void do_newlevel(const char *newlevel) setenv("RC_RUNLEVEL", newlevel, 1); rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; - run_script(INITSH); + run_program(INITSH); #ifdef __linux__ /* If we requested a runlevel, save it now */ @@ -1050,8 +1038,7 @@ int main(int argc, char **argv) rc_logger_open(newlevel ? newlevel : runlevel); /* Setup a signal handler */ - if (signal_setup(SIGINT, handle_signal) != 0) - eerror ("signal_setup: %s", strerror(errno)); + signal_setup(SIGINT, handle_signal); signal_setup(SIGQUIT, handle_signal); signal_setup(SIGTERM, handle_signal); signal_setup(SIGUSR1, handle_signal); |