diff --git a/src/service.c b/src/service.c index 673d8799..779e513d 100644 --- a/src/service.c +++ b/src/service.c @@ -948,6 +948,61 @@ static void service_kill(svc_t *svc) print(2, NULL); } +/* + * Call script with MAINPID environment set, and any environment specified + * by env:file, wait for completion before resuming operation. + * + * Called by service_stop() and service_reload() when alternate mechanisms + * for stopping and reloading have been specified by the user. + */ +static int service_run_script(svc_t *svc, char *script) +{ + const char *id = svc_ident(svc, NULL, 0); + pid_t pid = service_fork(svc); + int status, rc; + + if (pid < 0) { + err(1, "%s: failed forking off script %s", id, script); + return 1; + } + + if (pid == 0) { + char *argv[4] = { + "sh", + "-c", + script, + NULL + }; + char pidbuf[16]; + + snprintf(pidbuf, sizeof(pidbuf), "%d", svc->pid); + setenv("MAINPID", pidbuf, 1); + + sig_unblock(); + execvp(_PATH_BSHELL, argv); + _exit(EX_OSERR); + } + + dbg("%s: script '%s' started as PID %d", id, script, pid); + if (waitpid(pid, &status, 0) == -1) { + warn("%s: failed calling script %s", id, script); + return -1; + } + + rc = WEXITSTATUS(status); + if (WIFEXITED(status)) { + dbg("%s: script '%s' exited without signal, status: %d", id, script, rc); + } else if (WIFSIGNALED(status)) { + dbg("%s: script '%s' terminated by signal %d", id, script, WTERMSIG(status)); + if (!rc) + rc = 1; + } else { + dbg("%s: script '%s' exited with status: %d", id, script, rc); + } + + return rc; +} + /* Ensure we don't have any notify socket lingering */ static void service_notify_stop(svc_t *svc) { @@ -1060,7 +1115,7 @@ int service_stop(svc_t *svc) print_desc("Stopping ", svc->desc); if (svc->stop_script[0]) { - rc = run(svc->stop_script, NULL); + rc = service_run_script(svc, svc->stop_script); } else if (!svc_is_sysv(svc)) { if (svc->pid > 1) { /* @@ -1151,7 +1206,7 @@ static int service_reload(svc_t *svc) if (svc->reload_script[0]) { logit(LOG_CONSOLE | LOG_NOTICE, "%s[%d], calling reload:%s ...", id, svc->pid, svc->reload_script); - rc = run(svc->reload_script, NULL); + rc = service_run_script(svc, svc->reload_script); } else if (svc->sighup) { if (svc->pid <= 1) { dbg("%s[%d]: bad PID, cannot reload service", id, svc->pid);