Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 63 additions & 36 deletions src/openrc-run/openrc-run.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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);
}

Expand All @@ -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();

Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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 */
Expand All @@ -799,7 +819,6 @@ static void svc_start_real(void)
tmplist = NULL;
}

hook_out = 0;
rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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()) {
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
28 changes: 15 additions & 13 deletions src/openrc/rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -954,26 +954,31 @@ 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, &regen)) == NULL)
if ((main_deptree = _rc_deptree_load(0, &regen)) == 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!");

/* 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
Expand Down Expand Up @@ -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);

Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading