diff options
author | Roy Marples <roy@marples.name> | 2009-04-23 20:20:17 +0000 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2009-04-23 20:20:17 +0000 |
commit | 7dc9c39503ded408c34ba6cd96ebdab352fbb6a6 (patch) | |
tree | 32ef5df0e73ff89cdceeec54439da091625092c7 /src | |
parent | 953b0b74357d28a1ec28ca13fbdeaa126fa2bbaa (diff) |
Improve the service timeout code and reduce the timeout to 60 seconds.
Don't process any dependencies when changing runlevels and called
outside of RC otherwise we can deadlock.
Diffstat (limited to 'src')
-rw-r--r-- | src/rc/runscript.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/src/rc/runscript.c b/src/rc/runscript.c index a727ba07..8cfe5039 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -71,13 +71,9 @@ #define PREFIX_LOCK RC_SVCDIR "/prefix.lock" -/* usecs to wait while we poll the fifo */ -#define WAIT_INTERVAL 20000000 - -/* max secs to wait until a service comes up */ -#define WAIT_MAX 300 - -#define ONE_SECOND 1000000000 +#define WAIT_INTERVAL 20000000 /* usecs to poll the lock file */ +#define WAIT_TIMEOUT 60 /* seconds until we timeout */ +#define WARN_TIMEOUT 10 /* warn about this every N seconds */ static const char *applet = NULL; static RC_STRINGLIST *applet_list = NULL; @@ -480,12 +476,10 @@ static bool svc_wait(const char *svc) { char file[PATH_MAX]; - struct timespec ts; - int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL); - int sloops = (ONE_SECOND / WAIT_INTERVAL) * 5; int fd; bool forever = false; RC_STRINGLIST *keywords; + struct timespec interval, timeout, warn; /* Some services don't have a timeout, like fsck */ keywords = rc_deptree_depend(deptree, svc, "keyword"); @@ -495,10 +489,14 @@ svc_wait(const char *svc) snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", basename_c(svc)); - ts.tv_sec = 0; - ts.tv_nsec = WAIT_INTERVAL; - while (nloops) { + interval.tv_sec = 0; + interval.tv_nsec = WAIT_INTERVAL; + timeout.tv_sec = WAIT_TIMEOUT; + timeout.tv_nsec = 0; + warn.tv_sec = WARN_TIMEOUT; + warn.tv_nsec = 0; + for (;;) { fd = open(file, O_RDONLY | O_NONBLOCK); if (fd != -1) { if (flock(fd, LOCK_SH | LOCK_NB) == 0) { @@ -510,23 +508,25 @@ svc_wait(const char *svc) if (errno == ENOENT) return true; if (errno != EWOULDBLOCK) - eerrorx("%s: open `%s': %s", applet, file, strerror(errno)); - - if (nanosleep(&ts, NULL) == -1) { + eerrorx("%s: open `%s': %s", applet, file, + strerror(errno)); + if (nanosleep(&interval, NULL) == -1) { if (errno != EINTR) return false; } - if (!forever) { - nloops --; - - if (--sloops == 0) { - ewarn("%s: waiting for %s", applet, svc); - sloops = (ONE_SECOND / WAIT_INTERVAL) * 5; + timespecsub(&timeout, &interval, &timeout); + if (timeout.tv_sec <= 0) + return false; + timespecsub(&warn, &interval, &warn); + if (warn.tv_sec <= 0) { + ewarn("%s: waiting for %s (%zu)", applet, svc, + timeout.tv_sec); + warn.tv_sec = WARN_TIMEOUT; + warn.tv_nsec = 0; } } } - return false; } @@ -1178,6 +1178,12 @@ runscript(int argc, char **argv) case_RC_COMMON_GETOPT } + /* If we're changing runlevels and not called by rc then we cannot + work with any dependencies */ + if (deps && getenv("RC_PID") == NULL && + (rc_runlevel_starting() || rc_runlevel_stopping())) + deps = false; + /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service that is being called and not any dependents */ if (getenv("IN_BACKGROUND")) { @@ -1272,7 +1278,7 @@ runscript(int argc, char **argv) RC_SERVICE_STARTED) svc_restart(deps); } else if (strcmp(optarg, "restart") == 0) { - svc_restart (deps); + svc_restart(deps); } else if (strcmp(optarg, "start") == 0) { svc_start(deps); } else if (strcmp(optarg, "stop") == 0) { |