diff --git a/src/openrc-run/openrc-run.c b/src/openrc-run/openrc-run.c index 4d8c4c753..22445b08a 100644 --- a/src/openrc-run/openrc-run.c +++ b/src/openrc-run/openrc-run.c @@ -93,7 +93,6 @@ static RC_STRINGLIST *restart_services; static RC_STRINGLIST *need_services; static RC_STRINGLIST *use_services; static RC_STRINGLIST *want_services; -static RC_HOOK hook_out; static int exclusive_fd = -1, master_tty = -1; static bool in_background, deps, dry_run; static volatile bool sighup, skip_mark, timedout; @@ -234,14 +233,6 @@ cleanup(void) restore_state(); if (!rc_in_plugin) { - if (hook_out) { - rc_plugin_run(hook_out, applet); - if (hook_out == RC_HOOK_SERVICE_START_DONE) - rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); - else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) - rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); - } - if (restart_services) start_services(restart_services); } @@ -356,11 +347,21 @@ svc_exec(const char *command) }; /* Setup our signal pipe */ - if (pipe2(signal_pipe, O_CLOEXEC) == -1) + if (pipe2(signal_pipe, O_CLOEXEC) == -1) { + if (!strcmp(command, "start")) + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); + else if (!strcmp(command, "stop")) + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("%s: pipe2: %s", applet, applet); + } - if ((errno = posix_spawn_file_actions_init(&tty))) + if ((errno = posix_spawn_file_actions_init(&tty))) { + if (!strcmp(command, "start")) + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); + else if (!strcmp(command, "stop")) + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("%s: posix_spawn_file_actions_init: %s", applet, strerror(errno)); + } /* Open a pty for our prefixed output * We do this instead of mapping pipes to stdout, stderr so that @@ -382,8 +383,13 @@ svc_exec(const char *command) fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); if ((errno = posix_spawn_file_actions_adddup2(&tty, slave_tty, STDOUT_FILENO)) - || (errno = posix_spawn_file_actions_adddup2(&tty, slave_tty, STDERR_FILENO))) + || (errno = posix_spawn_file_actions_adddup2(&tty, slave_tty, STDERR_FILENO))) { + if (!strcmp(command, "start")) + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); + else if (!strcmp(command, "stop")) + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("%s: posix_spawn_file_actions_adddup2: %s", applet, strerror(errno)); + } } if (faccessat(rc_dirfd(RC_DIR_SVCDIR), "openrc-run.sh", F_OK, 0) == 0) { @@ -395,8 +401,13 @@ svc_exec(const char *command) rc_environ_export(&env, (const char *const *) environ, &envp); einfov("Executing: %s %s %s", argv[0], service, command); - if ((errno = posix_spawn(&service_pid, argv[0], &tty, NULL, UNCONST(argv), envp ? UNCONST(envp) : environ))) + if ((errno = posix_spawn(&service_pid, argv[0], &tty, NULL, UNCONST(argv), envp ? UNCONST(envp) : environ))) { + if (!strcmp(command, "start")) + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); + else if (!strcmp(command, "stop")) + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("%s: exec '%s': %s", service, argv[0], strerror(errno)); + } posix_spawn_file_actions_destroy(&tty); free(openrc_sh); @@ -554,8 +565,10 @@ svc_start_check(void) state = rc_service_state(applet); if (in_background) { - if (!(state & (RC_SERVICE_INACTIVE | RC_SERVICE_STOPPED))) + if (!(state & (RC_SERVICE_INACTIVE | RC_SERVICE_STOPPED))) { + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); exit(EXIT_FAILURE); + } if (rc_yesno(getenv("IN_HOTPLUG"))) rc_service_mark(applet, RC_SERVICE_HOTPLUGGED); if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0) @@ -564,6 +577,7 @@ svc_start_check(void) if (state & RC_SERVICE_STARTED) { ewarn("WARNING: %s has already been started", applet); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); exit(EXIT_SUCCESS); } else if (state & RC_SERVICE_INACTIVE && !in_background) { ewarnx("WARNING: %s has already started, but is inactive", applet); @@ -572,17 +586,18 @@ svc_start_check(void) if (exclusive_fd == -1) exclusive_fd = svc_lock(applet, !deps); if (exclusive_fd == -1) { - if (errno != EWOULDBLOCK) + if (errno != EWOULDBLOCK) { + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); eerrorx("%s: failed to acquire lock: %s", applet, strerror(errno)); - else if (state & RC_SERVICE_STOPPING) + } else if (state & RC_SERVICE_STOPPING) { ewarnx("WARNING: %s is stopping", applet); - else + } else { ewarnx("WARNING: %s is already starting", applet); + } } fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); rc_service_mark(applet, RC_SERVICE_STARTING); - hook_out = RC_HOOK_SERVICE_START_OUT; rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); } @@ -602,8 +617,10 @@ svc_start_deps(void) if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; - if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) + if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) { + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); eerrorx("failed to load deptree"); + } if (!deptypes_b) setup_deptypes(); @@ -620,6 +637,7 @@ svc_start_deps(void) fprintf(stderr, "%s", svc->value); } fprintf(stderr, "\n"); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); exit(EXIT_FAILURE); } rc_stringlist_free(services); @@ -684,10 +702,12 @@ svc_start_deps(void) continue; } if (rc_stringlist_find(need_services, svc->value)) { - if (state & (RC_SERVICE_INACTIVE | RC_SERVICE_WASINACTIVE)) + if (state & (RC_SERVICE_INACTIVE | RC_SERVICE_WASINACTIVE)) { rc_stringlist_add(tmplist, svc->value); - else if (!TAILQ_FIRST(tmplist)) + } else if (!TAILQ_FIRST(tmplist)) { + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); eerrorx("ERROR: cannot start %s as %s would not start", applet, svc->value); + } } } @@ -758,22 +778,22 @@ static void svc_start_real(void) if (ibsave) setenv("IN_BACKGROUND", ibsave, 1); - hook_out = RC_HOOK_SERVICE_START_DONE; rc_plugin_run(RC_HOOK_SERVICE_START_NOW, applet); skip_mark = false; started = (svc_exec("start") == 0); if (ibsave) unsetenv("IN_BACKGROUND"); - if (rc_service_state(applet) & RC_SERVICE_INACTIVE) + if (rc_service_state(applet) & RC_SERVICE_INACTIVE) { ewarnx("WARNING: %s has started, but is inactive", applet); - else if (!started) + } else if (!started) { + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); eerrorx("ERROR: %s failed to start", applet); + } if (!skip_mark) rc_service_mark(applet, RC_SERVICE_STARTED); exclusive_fd = svc_unlock(applet, exclusive_fd); - hook_out = RC_HOOK_SERVICE_START_OUT; rc_plugin_run(RC_HOOK_SERVICE_START_DONE, applet); /* Now start any scheduled services */ @@ -799,7 +819,6 @@ static void svc_start_real(void) tmplist = NULL; } - hook_out = 0; rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); } @@ -827,11 +846,15 @@ svc_stop_check(RC_SERVICE *state) { *state = rc_service_state(applet); - if (rc_runlevel_stopping() && *state & RC_SERVICE_FAILED) + if (rc_runlevel_stopping() && *state & RC_SERVICE_FAILED) { + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); exit(EXIT_FAILURE); + } - if (in_background && !(*state & (RC_SERVICE_STARTED) && !(*state & RC_SERVICE_INACTIVE))) + if (in_background && !(*state & (RC_SERVICE_STARTED) && !(*state & RC_SERVICE_INACTIVE))) { + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); exit(EXIT_FAILURE); + } if (*state & RC_SERVICE_STOPPED) { ewarn("WARNING: %s is already stopped", applet); @@ -841,6 +864,7 @@ svc_stop_check(RC_SERVICE *state) if (exclusive_fd == -1) exclusive_fd = svc_lock(applet, !deps); if (exclusive_fd == -1) { + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); if (errno != EWOULDBLOCK) eerrorx("%s: failed to acquire lock: %s", applet, strerror(errno)); else if (*state & RC_SERVICE_STOPPING) @@ -850,7 +874,6 @@ svc_stop_check(RC_SERVICE *state) fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); rc_service_mark(applet, RC_SERVICE_STOPPING); - hook_out = RC_HOOK_SERVICE_STOP_OUT; rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); if (!rc_runlevel_stopping()) { @@ -877,8 +900,10 @@ svc_stop_deps(RC_SERVICE state) if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; - if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) + if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) { + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("failed to load deptree"); + } if (!deptypes_m) setup_deptypes(); @@ -924,6 +949,7 @@ svc_stop_deps(RC_SERVICE state) continue; rc_service_mark(applet, RC_SERVICE_FAILED); } + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("ERROR: cannot stop %s as %s is still up", applet, svc->value); } rc_stringlist_free(tmplist); @@ -969,22 +995,21 @@ svc_stop_real(void) if (ibsave) setenv("IN_BACKGROUND", ibsave, 1); - hook_out = RC_HOOK_SERVICE_STOP_DONE; rc_plugin_run(RC_HOOK_SERVICE_STOP_NOW, applet); skip_mark = false; stopped = (svc_exec("stop") == 0); if (ibsave) unsetenv("IN_BACKGROUND"); - if (!stopped) + if (!stopped) { + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); eerrorx("ERROR: %s failed to stop", applet); + } if (!skip_mark) rc_service_mark(applet, in_background ? RC_SERVICE_INACTIVE : RC_SERVICE_STOPPED); - hook_out = RC_HOOK_SERVICE_STOP_OUT; rc_plugin_run(RC_HOOK_SERVICE_STOP_DONE, applet); - hook_out = 0; rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); } @@ -1086,8 +1111,9 @@ resolve_deptype(void) if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; - if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) + if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) { eerrorx("failed to load deptree"); + } tmplist = rc_stringlist_new(); rc_stringlist_add(tmplist, optarg); @@ -1147,8 +1173,9 @@ static int cmd_zap(void) { einfo("Manually resetting %s to stopped state", applet); - if (!rc_service_mark(applet, RC_SERVICE_STOPPED)) + if (!rc_service_mark(applet, RC_SERVICE_STOPPED)) { eerrorx("rc_service_mark: %s", strerror(errno)); + } unhotplug(); return 0; diff --git a/src/openrc/rc.c b/src/openrc/rc.c index f7ab41a16..0216a6ab6 100644 --- a/src/openrc/rc.c +++ b/src/openrc/rc.c @@ -81,7 +81,6 @@ static RC_STRINGLIST *main_types_nw; static RC_STRINGLIST *main_types_nwua; static RC_DEPTREE *main_deptree; static char *runlevel; -static RC_HOOK hook_out; struct termios *termios_orig = NULL; @@ -117,9 +116,6 @@ cleanup(void) if (!rc_in_logger && !rc_in_plugin && applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0)) { - if (hook_out) - rc_plugin_run(hook_out, runlevel); - rc_plugin_unload(); if (termios_orig) { @@ -229,8 +225,10 @@ run_program(const char *prog) sigprocmask(SIG_SETMASK, &full, &old); pid = fork(); - if (pid == -1) + if (pid == -1) { + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); eerrorx("%s: fork: %s", applet, strerror(errno)); + } if (pid == 0) { /* Restore default handlers */ sigaction(SIGCHLD, &sa, NULL); @@ -255,8 +253,10 @@ run_program(const char *prog) /* Unmask signals and wait for child */ sigprocmask(SIG_SETMASK, &old, NULL); - if (rc_waitpid(pid) == -1) + if (rc_waitpid(pid) == -1) { + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); eerrorx("%s: failed to exec `%s'", applet, prog); + } } static void @@ -954,17 +954,20 @@ int main(int argc, char **argv) } else { rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, runlevel); } - hook_out = RC_HOOK_RUNLEVEL_STOP_OUT; /* Check if runlevel is valid if we're changing */ if (newlevel && strcmp(runlevel, newlevel) != 0 && !going_down) { - if (!rc_runlevel_exists(newlevel)) + if (!rc_runlevel_exists(newlevel)) { + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); eerrorx("%s: is not a valid runlevel", newlevel); + } } /* Load our deptree */ - if ((main_deptree = _rc_deptree_load(0, ®en)) == NULL) + if ((main_deptree = _rc_deptree_load(0, ®en)) == NULL) { + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); eerrorx("failed to load deptree"); + } if (faccessat(rc_dirfd(RC_DIR_SVCDIR), "clock-skewed", F_OK, 0) == 0) ewarn("WARNING: clock skew detected!"); @@ -972,8 +975,10 @@ int main(int argc, char **argv) /* Clean the failed services state dir */ clean_failed(); - if (mkdirat(rc_dirfd(RC_DIR_SVCDIR), "rc.stopping", 0755) != 0) + if (mkdirat(rc_dirfd(RC_DIR_SVCDIR), "rc.stopping", 0755) != 0) { + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); eerrorx("%s: failed to create stopping dir '%s/rc.stopping': %s", applet, rc_svcdir(), strerror(errno)); + } /* Create a list of all services which we could stop (assuming * they won't be active in the new or current runlevel) including @@ -1052,7 +1057,6 @@ int main(int argc, char **argv) /* Notify the plugins we have finished */ rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, going_down ? newlevel : runlevel); - hook_out = 0; unlinkat(rc_dirfd(RC_DIR_SVCDIR), "rc.stopping", AT_REMOVEDIR); @@ -1074,7 +1078,6 @@ int main(int argc, char **argv) mkdirat(rc_dirfd(RC_DIR_SVCDIR), "rc.starting", 0755); rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel); - hook_out = RC_HOOK_RUNLEVEL_START_OUT; /* Re-add our hotplugged services if they stopped */ if (main_hotplugged_services) @@ -1135,7 +1138,6 @@ int main(int argc, char **argv) #endif rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); - hook_out = 0; /* If we're in the boot runlevel and we regenerated our dependencies * we need to delete them so that they are regenerated again in the