diff --git a/src/cond-w.c b/src/cond-w.c index cd127cce..e4525fed 100644 --- a/src/cond-w.c +++ b/src/cond-w.c @@ -297,10 +297,17 @@ int cond_set_noupdate(const char *name) void cond_set(const char *name) { + svc_t *svc; + _d("%s", name); if (cond_set_noupdate(name)) return; + /* XXX: refactor when new notify framework is in place */ + svc = svc_find_by_cond(name); + if (svc && svc_has_ready(svc)) + service_ready_script(svc); + cond_update(name); } diff --git a/src/service.c b/src/service.c index 3d678d4e..99c0687d 100644 --- a/src/service.c +++ b/src/service.c @@ -1266,6 +1266,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) char *name = NULL, *halt = NULL, *delay = NULL; char *id = NULL, *env = NULL, *cgroup = NULL; char *pre_script = NULL, *post_script = NULL; + char *ready_script = NULL; struct tty tty = { 0 }; char *dev = NULL; int respawn = 0; @@ -1361,6 +1362,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) pre_script = arg; else if (MATCH_CMD(cmd, "post:", arg)) post_script = arg; + else if (MATCH_CMD(cmd, "ready:", arg)) + ready_script = arg; else if (MATCH_CMD(cmd, "env:", arg)) env = arg; else if (MATCH_CMD(cmd, "cgroup:", arg)) @@ -1516,6 +1519,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) parse_script("pre", pre_script, svc->pre_script, sizeof(svc->pre_script)); if (post_script) parse_script("post", post_script, svc->post_script, sizeof(svc->post_script)); + if (ready_script) + parse_script("ready", ready_script, svc->ready_script, sizeof(svc->ready_script)); if (log) parse_log(svc, log); if (desc) @@ -1607,7 +1612,8 @@ void service_monitor(pid_t lost, int status) svc = svc_find_by_pid(lost); if (!svc) { - _d("collected unknown PID %d", lost); + if (service_script_del(lost)) + _d("collected unknown PID %d", lost); return; } @@ -1805,6 +1811,43 @@ static void service_post_script(svc_t *svc) service_timeout_after(svc, svc->killdelay, service_kill_script); } +void service_ready_script(svc_t *svc) +{ + pid_t pid; + + if (access(svc->ready_script, X_OK)) + return; + + pid = service_fork(svc); + if (pid < 0) { + _pe("Failed forking off %s ready-script %s", svc_ident(svc, NULL, 0), svc->ready_script); + return; + } + + if (pid == 0) { + char buf[CMD_SIZE]; + char *argv[4] = { + "sh", + "-ac", + buf, + NULL + }; + char *env_file; + + env_file = svc_getenv(svc); + if (env_file) + snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->ready_script); + else + strlcpy(buf, svc->ready_script, sizeof(buf)); + + set_pre_post_envs(svc, "ready"); + execvp(_PATH_BSHELL, argv); + _exit(EX_OSERR); + } + + service_script_add(svc, pid); +} + static void service_retry(svc_t *svc) { char *restart_cnt = (char *)&svc->restart_cnt; diff --git a/src/service.h b/src/service.h index 9831ea05..ba33a834 100644 --- a/src/service.h +++ b/src/service.h @@ -35,6 +35,8 @@ void service_runtask_clean (void); void service_reload_dynamic (void); void service_update_rdeps (void); +void service_ready_script (svc_t *svc); /* XXX: only for pidfile plugin before notify framework */ + int service_timeout_after (svc_t *svc, int timeout, void (*cb)(svc_t *svc)); int service_timeout_cancel (svc_t *svc); diff --git a/src/svc.h b/src/svc.h index ac787968..3b000c70 100644 --- a/src/svc.h +++ b/src/svc.h @@ -183,6 +183,7 @@ typedef struct svc { char env[MAX_ARG_LEN]; char pre_script[MAX_ARG_LEN]; char post_script[MAX_ARG_LEN]; + char ready_script[MAX_ARG_LEN]; /* * Used to forcefully kill services that won't shutdown on @@ -239,6 +240,7 @@ static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sigh static inline int svc_has_pidfile (svc_t *svc) { return svc_is_daemon(svc) && svc->pidfile[0] != 0 && svc->pidfile[0] != '!'; } static inline int svc_has_pre (svc_t *svc) { return svc->pre_script[0]; } static inline int svc_has_post (svc_t *svc) { return svc->post_script[0]; } +static inline int svc_has_ready (svc_t *svc) { return svc->ready_script[0];} static inline void svc_starting (svc_t *svc) { if (svc) svc->starting = 1; } static inline void svc_started (svc_t *svc) { if (svc) svc->starting = 0; }