Support for monitoring forking services/sysv daemons

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2020-02-26 14:10:47 +01:00
1 parent f6372de6a9
commit decdc1560a
5 files changed
+55 -9

No files matched your search

+2
View File
@@ -12,6 +12,8 @@ Bug fix release, but also cgroups and a new progress!
https://twitter.com/b0rk/status/1214341831049252870?s=20 https://twitter.com/b0rk/status/1214341831049252870?s=20
### Changes ### Changes
* Support for `sysv` start/stop scripts as well as monitoring forking
services, stared using `sysv` or `service` stanza
* Add support for `--disable-docs` and `--disable-contrib` to speed up * Add support for `--disable-docs` and `--disable-contrib` to speed up
builds and work around issue with massively parallel builds builds and work around issue with massively parallel builds
* Add `-b`, batch mode, for non-interactive use to `initctl` * Add `-b`, batch mode, for non-interactive use to `initctl`
+20 -9
View File
@@ -160,17 +160,28 @@ Syntax
When entering an allowed runlevel, Finit calls `init-script start`, When entering an allowed runlevel, Finit calls `init-script start`,
when entering a disallowed runlevel, Finit calls `init-script stop`, when entering a disallowed runlevel, Finit calls `init-script stop`,
and if the Finit .conf, where `sysv` stanza is declared, is modified, and if the Finit .conf, where `sysv` stanza is declared, is modified,
Finit calls `init-script restart` on `initctl restart`. Similar Finit calls `init-script restart` on `initctl reload`. Similar to
to how a `service` stanza works. how `service` stanzas work.
> **Note:** there is currently now supervision of daemons started as
> sysv services. I.e., the `pid:!...` support is still missing.
Forking services started with `sysv` scripts can be monitored by Finit
by declaring the PID file to look for: `pid:!/path/to/pidfile.pid`.
* `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description` * `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
Service, or daemon, to be monitored and automatically restarted if it Service, or daemon, to be monitored and automatically restarted if it
exits prematurely. Please note that you often need to provide a exits prematurely.
`--foreground` or `--no-background` argument to most daemons to
prevent them from forking off a sub-process in the background. For daemons that support it, we recommend appending `--foreground`, or
`--no-background`, argument to prevent them from forking off a
sub-process in the background. This is the most reliable way to
monitor a service.
However, not all daemons support running in the foreground, or they
may start logging to the foreground as well, these are called forking
services and are supported using the same syntax as forking `sysv`
services, using the `pid:!/path/to/pidfile.pid` syntax.
In the case of `ospfd` (below), we omit the `-d` flag to prevent it
from forking (daemonizing):
```shell ```shell
service [2345] <svc/sbin/zebra> /sbin/ospfd -- OSPF daemon service [2345] <svc/sbin/zebra> /sbin/ospfd -- OSPF daemon
@@ -198,7 +209,7 @@ Syntax
can depend on `<svc/foo>`. can depend on `<svc/foo>`.
If a service `bar` *does* maintain a PID file, but using `foo.pid`, we If a service `bar` *does* maintain a PID file, but using `foo.pid`, we
can inform Finit of this by simplly prepending an `!` to the argument. can inform Finit of this by prepending an `!` to the argument.
pid:!/run/foo.pid pid:!/run/foo.pid
+10
View File
@@ -29,6 +29,7 @@
#include "finit.h" #include "finit.h"
#include "cond.h" #include "cond.h"
#include "helpers.h" #include "helpers.h"
#include "pid.h"
#include "plugin.h" #include "plugin.h"
#include "service.h" #include "service.h"
@@ -66,6 +67,15 @@ static void pidfile_callback(void *arg, int fd, int events)
mkcond(cond, sizeof(cond), svc->cmd); mkcond(cond, sizeof(cond), svc->cmd);
if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) { if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
svc_started(svc); svc_started(svc);
if (svc_is_forking(svc)) {
pid_t pid;
pid = pid_file_read(pid_file(svc));
_d("Forking service %s changed PID from %d to %d",
svc->cmd, svc->pid, pid);
svc->pid = pid;
}
cond_set(cond); cond_set(cond);
} else if (ev->mask & IN_DELETE) } else if (ev->mask & IN_DELETE)
cond_clear(cond); cond_clear(cond);
+22
View File
@@ -485,7 +485,25 @@ static int service_stop(svc_t *svc)
print_desc("Stopping ", svc->desc); print_desc("Stopping ", svc->desc);
if (!svc_is_sysv(svc)) { if (!svc_is_sysv(svc)) {
if (svc->pid <= 1)
goto cleanup;
res = kill(svc->pid, SIGTERM); res = kill(svc->pid, SIGTERM);
/* PID lost or forking process never really started */
if (res == -1 && ESRCH == errno) {
char *fn;
/* XXX: Same clenup as done by service_monitor(), refactor */
cleanup:
fn = pid_file(svc);
if (remove(fn) && errno != ENOENT)
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
basename(svc->cmd), fn);
/* No longer running, update books. */
svc->start_time = svc->pid = 0;
}
} else { } else {
char *args[] = { svc->cmd, "stop", NULL }; char *args[] = { svc->cmd, "stop", NULL };
pid_t pid; pid_t pid;
@@ -1042,6 +1060,10 @@ void service_monitor(pid_t lost, int status)
svc->cmd, lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status)); svc->cmd, lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status));
svc->status = status; svc->status = status;
/* Forking sysv/services declare themselves with pid:!/path/to/pid.file */
if (svc_is_starting(svc) && svc_is_forking(svc))
return;
/* Try removing PID file (in case service does not clean up after itself) */ /* Try removing PID file (in case service does not clean up after itself) */
if (svc_is_daemon(svc)) { if (svc_is_daemon(svc)) {
char *fn; char *fn;
+1
View File
@@ -187,6 +187,7 @@ static inline int svc_is_inetd_conn(svc_t *svc) { return svc && SVC_TYPE_INETD_C
static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; } static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; }
static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; } static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; }
static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type); } static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type); }
static inline int svc_is_forking (svc_t *svc) { return (svc_is_daemon(svc) || svc_is_sysv(svc)) && svc->pidfile[0] == '!'; }
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); } 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 int svc_has_sighup (svc_t *svc) { return svc && 0 != svc->sighup; }