Fix #109: Support PID files in subdirectories to /var/run

Services, like dbus and teamd for instance, may create their PID files
in a subdirectory of /var/run (today often /run). E.g.,

   - /var/run/teamd/a1.pid    -- For aggregate A1
   - /var/run/dbus/pid
   - /var/run/lxc/foo.pid     -- For container foo

This patch adds support for dynamically adding inotify watchers to any
new subdirectory created in /var/run (discarding too deep directories).

To match services in this directory the run/task/service/sysv stanza
must contain the pid:!/path/to/pidfile.pid syntax.  This pid file name
is also used to create the condition this service asserts using the
following formula:

   svc/ + <dirname of service> + <subdir and file without .pid>

E.g., the case of teamd (above) gives condition 'svc/usr/bin/teamd/a1'

The special case of dbus is interesting, since it may not be a special
case, but rather the norm for services using a subdirectory.  It is
handled as follows; when a new subdirectory is detected, the directory
is scanned for files matching *.pid.  Matching files follow the teamd
case.  The directory is also scanned for 'pid', which then gives us the
condition 'svc/usr/bin/dbus'

One last example, illustrated by lxc-start, where we want to track the
condition for the LXC container foo.  The service stanza:

   service pid:!/run/lxc/foo.pid lxc-start -n foo -F -p /run/lxc/foo.pid -- Container foo

This command has no leading path so the condition is composed entirely
from the PID file location:

   svc/  + '' + lxc/foo => svc/lxc/foo

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2020-02-28 16:39:53 +01:00
1 parent 97ce0aa519
commit 54cfa74042
6 files changed
+275 -54

No files matched your search

+62
View File
@@ -31,6 +31,68 @@
#include "pid.h"
#include "service.h"
/*
* The service condition name is constructed from the 'svc/' prefix, the
* dirname of the svc->cmd, e.g., '/usr/bin/teamd' => 'usr/bin', and the
* service's pid:filename, including an optional subdirectory, without
* the .pid extension.
*
* The following example uses the team (aggregate) service:
*
* service pid:!/run/teamd/a1.pid /usr/bin/teamd -f /etc/teamd/a1.conf
*
* => 'svc/' + 'usr/bin' + 'teamd/a1' => svc/usr/bin/teamd/a1
*
* The next example uses the dbus-daemon:
*
* service pid:!/run/dbus/pid /usr/bin/dbus-daemon
*
* => 'svc/' + 'usr/bin' + 'dbus' => svc/usr/bin/dbus
*
* The last example uses lxc-start to start container foo:
*
* service pid:!/run/lxc/foo.pid lxc-start -n foo -F -p /run/lxc/foo.pid -- Container foo
*
* => 'svc/' + '' + 'lxc/foo' => svc/lxc/foo
*/
char *mkcond(svc_t *svc, char *buf, size_t len)
{
char path[256];
char *pidfile;
char *ptr;
strlcpy(path, svc->cmd, sizeof(path));
ptr = rindex(path, '/');
if (ptr)
*ptr = 0;
else
path[0] = 0;
pidfile = pid_file(svc);
ptr = strstr(pidfile, "run");
if (ptr)
ptr += 3;
else
ptr = rindex(pidfile, '/');
snprintf(buf, len, "svc%s%s%s", path[0] != 0 && path[0] != '/' ? "/" : "", path, ptr);
_d("Composed condition from cmd %s (path %s) and pidfile %s => %s", svc->cmd, path, ptr, buf);
/* Case: /var/run/dbus/pid */
ptr = strstr(buf, "/pid");
if (ptr && !strcmp(ptr, "/pid"))
*ptr = 0;
/* Case /var/run/teamd/a1.pid */
ptr = strstr(buf, ".pid");
if (ptr && !strcmp(ptr, ".pid"))
*ptr = 0;
_d("Creating condition => %s", buf);
return buf;
}
static int cond_set_gen(const char *file, unsigned int gen)
{
char *ptr, path[256];
-7
View File
@@ -29,13 +29,6 @@
#include "pid.h"
#include "service.h"
char *mkcond(char *buf, size_t len, char *nm)
{
snprintf(buf, len, "svc%s%s", nm[0] != '/' ? "/" : "", nm);
return buf;
}
const char *condstr(enum cond_state s)
{
static const char *strs[] = {
+2 -1
View File
@@ -2,6 +2,7 @@
#define FINIT_COND_H_
#include <paths.h>
#include <svc.h>
#define COND_DIR "finit/cond"
#define COND_PATH _PATH_VARRUN COND_DIR
@@ -13,7 +14,7 @@ typedef enum cond_state {
COND_ON
} cond_state_t;
char *mkcond (char *buf, size_t len, char *nm);
char *mkcond (svc_t *svc, char *buf, size_t len);
const char *condstr (enum cond_state s);
const char *cond_path (const char *name);
unsigned int cond_get_gen (const char *path);
+1 -1
View File
@@ -1353,7 +1353,7 @@ restart:
if (!svc_is_changed(svc)) {
char name[MAX_COND_LEN];
mkcond(name, sizeof(name), svc->cmd);
mkcond(svc, name, sizeof(name));
cond_set_path(cond_path(name), COND_ON);
}
break;
+1 -1
View File
@@ -60,7 +60,7 @@ static void svc_gc(void *arg)
continue;
TAILQ_REMOVE(&gc_list, svc, link);
cond_clear(mkcond(cond, sizeof(cond), svc->cmd));
cond_clear(mkcond(svc, cond, sizeof(cond)));
free(svc);
}