diff --git a/src/openrc-run/openrc-run.c b/src/openrc-run/openrc-run.c index f8c163941..0664fc055 100644 --- a/src/openrc-run/openrc-run.c +++ b/src/openrc-run/openrc-run.c @@ -554,23 +554,25 @@ svc_start_check(void) ewarnx("WARNING: %s will be started in the next runlevel", applet); } + if (state & RC_SERVICE_STARTED) { + ewarn("WARNING: %s has already been started", applet); + exit(EXIT_SUCCESS); + } else if (state & RC_SERVICE_INACTIVE && !in_background) { + ewarnx("WARNING: %s has already started, but is inactive", applet); + } + if (exclusive_fd == -1) exclusive_fd = svc_lock(applet, !deps); if (exclusive_fd == -1) { - if (state & RC_SERVICE_STOPPING) + if (errno != EWOULDBLOCK) + eerrorx("%s: failed to acquire lock: %s", applet, strerror(errno)); + else if (state & RC_SERVICE_STOPPING) ewarnx("WARNING: %s is stopping", applet); else ewarnx("WARNING: %s is already starting", applet); } fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); - if (state & RC_SERVICE_STARTED) { - ewarn("WARNING: %s has already been started", applet); - exit(EXIT_SUCCESS); - } else if (state & RC_SERVICE_INACTIVE && !in_background) { - ewarnx("WARNING: %s has already started, but is inactive", applet); - } - rc_service_mark(applet, RC_SERVICE_STARTING); hook_out = RC_HOOK_SERVICE_START_OUT; rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); @@ -631,6 +633,10 @@ svc_start_deps(void) printf(" %s", svc->value); continue; } + /* FIXME(NRK): service_start() can return -1 on + * failure and feeding that to rc_waitpid seems + * very suspicious. needs investigation. + */ pid = service_start(svc->value); if (!rc_conf_yesno("rc_parallel")) rc_waitpid(pid); @@ -789,20 +795,22 @@ svc_stop_check(RC_SERVICE *state) if (in_background && !(*state & (RC_SERVICE_STARTED | RC_SERVICE_INACTIVE))) exit(EXIT_FAILURE); + if (*state & RC_SERVICE_STOPPED) { + ewarn("WARNING: %s is already stopped", applet); + return 1; + } + if (exclusive_fd == -1) exclusive_fd = svc_lock(applet, !deps); if (exclusive_fd == -1) { - if (*state & RC_SERVICE_STOPPING) + if (errno != EWOULDBLOCK) + eerrorx("%s: failed to acquire lock: %s", applet, strerror(errno)); + else if (*state & RC_SERVICE_STOPPING) ewarnx("WARNING: %s is already stopping", applet); eerrorx("ERROR: %s stopped by something else", applet); } fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); - if (*state & RC_SERVICE_STOPPED) { - ewarn("WARNING: %s is already stopped", applet); - return 1; - } - rc_service_mark(applet, RC_SERVICE_STOPPING); hook_out = RC_HOOK_SERVICE_STOP_OUT; rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); diff --git a/src/shared/misc.c b/src/shared/misc.c index 50e436105..7d6bb0947 100644 --- a/src/shared/misc.c +++ b/src/shared/misc.c @@ -289,6 +289,7 @@ svc_lock(const char *applet, bool ignore_lock_failure) if (fd == -1) return -1; if (flock(fd, LOCK_EX | LOCK_NB) == -1) { + int saved_errno = errno; if (ignore_lock_failure) { /* Two services with a need b, and b's start() * calling restart --no-deps on a would cause @@ -299,6 +300,7 @@ svc_lock(const char *applet, bool ignore_lock_failure) } eerror("Call to flock failed: %s", strerror(errno)); close(fd); + errno = saved_errno; return -1; } return fd;