diff --git a/plugins/pidfile.c b/plugins/pidfile.c index d25a76f0..fee45573 100644 --- a/plugins/pidfile.c +++ b/plugins/pidfile.c @@ -44,13 +44,20 @@ static void pidfile_callback(void *UNUSED(arg), int fd, int UNUSED(events)) _d("%s: match %s", basename, svc->cmd); snprintf(cond, sizeof(cond), "svc%s", svc->cmd); - if (ev->mask & (IN_CREATE | IN_ATTRIB)) + if (ev->mask & (IN_CREATE | IN_ATTRIB)) { + svc_started(svc); cond_set(cond); - else if (ev->mask & IN_DELETE) + } else if (ev->mask & IN_DELETE) cond_clear(cond); } } +/* + * Assert condition only if the service is running, but not if it's + * recently been changed or while it's starting up. + * + * We must wait for the service to create/touch its pidfile. + */ static void pidfile_reconf(void *_null) { static char name[MAX_ARG_LEN]; @@ -59,14 +66,14 @@ static void pidfile_reconf(void *_null) (void)(_null); for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { - if (svc->state == SVC_RUNNING_STATE && !svc_is_changed(svc)) { + if (svc->state == SVC_RUNNING_STATE && !svc_is_changed(svc) && !svc_is_starting(svc)) { snprintf(name, MAX_ARG_LEN, "svc%s", svc->cmd); cond_set_path(cond_path(name), COND_ON); } } } -static void pidfile_init (void *arg) +static void pidfile_init(void *arg) { struct context *ctx = arg; diff --git a/service.c b/service.c index 36482a77..5794b0b2 100644 --- a/service.c +++ b/service.c @@ -151,6 +151,9 @@ static int service_start(svc_t *svc) return result; } + /* Declare we're waiting for svc to create its pidfile */ + svc_starting(svc); + /* Block sigchild while forking. */ sigemptyset(&nmask); sigaddset(&nmask, SIGCHLD); @@ -329,6 +332,9 @@ static int service_restart(svc_t *svc) if (verbose) print_desc("Restarting ", svc->desc); + /* Declare we're waiting for svc to re-assert/touch its pidfile */ + svc_starting(svc); + _d("Sending SIGHUP to PID %d", svc->pid); err = kill(svc->pid, SIGHUP); diff --git a/svc.h b/svc.h index 678f60fd..44172de7 100644 --- a/svc.h +++ b/svc.h @@ -88,6 +88,7 @@ typedef struct svc { time_t mtime; /* Modification time for .conf from /etc/finit.d/ */ const int dirty; /* Set if old mtime != new mtime => reloaded, * or -1 when marked for removal */ + int starting; /* ... waiting for pidfile to be re-asserted */ int runlevels; int sighup; /* This service supports SIGHUP :) */ svc_block_t block; /* Reason that this service is currently blocked */ @@ -168,6 +169,10 @@ int svc_is_unique (svc_t *svc); static inline int svc_in_runlevel(svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); } static inline int svc_has_sighup(svc_t *svc) { return svc && 0 != svc->sighup; } +static inline void svc_starting (svc_t *svc) { svc->starting = 1; } +static inline void svc_started (svc_t *svc) { svc->starting = 0; } +static inline int svc_is_starting(svc_t *svc) { 0 != svc->starting; } + static inline int svc_is_dynamic(svc_t *svc) { return svc && 0 != svc->mtime; } static inline int svc_is_removed(svc_t *svc) { return svc && -1 == svc->dirty; } static inline int svc_is_changed(svc_t *svc) { return svc && 0 != svc->dirty; }