From 56a89db889078a87f192496c537261cc649d8f87 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 26 Feb 2023 12:24:43 +0100 Subject: [PATCH] Add support run/task/service 'conflict:foo' handling Signed-off-by: Joachim Wiberg --- doc/config.md | 18 ++++++++++++++++++ src/service.c | 18 +++++++++++++++++- src/svc.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/svc.h | 2 ++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/doc/config.md b/doc/config.md index dbce328e..9ba327c9 100644 --- a/doc/config.md +++ b/doc/config.md @@ -721,6 +721,24 @@ optional `name` argument: name: +If multiple instances of a service, with the same `name`, exist. Set +the identifier `:ID` to prevent Finit from replacing previous instances: + + service :eth1 ssdpd eth1 -- Windows discovery on eth1 + service :eth2 ssdpd eth2 -- Windows discovery on eth2 + +If you have conflicting services and want to prevent them from starting, +use the `conflict:` argument: + + service [S12345789] udevd -- Device event management daemon + run [S] conflict:udevd mdev -s -- Populating device tree + +Multiple conflicting services can be separated using `,`: + + service :1 abc + service :2 abc + service conflict:abc:1,abc:2 cde + As mentioned previously, services are automatically restarted, this is configurable with the following options: diff --git a/src/service.c b/src/service.c index 0ff7afdd..f4e09d0b 100644 --- a/src/service.c +++ b/src/service.c @@ -605,6 +605,13 @@ static int service_start(svc_t *svc) } } + /* Don't start if it conflicts with something else already started */ + if (svc_conflicts(svc)) { + logit(LOG_INFO, "Not starting %s, conflicts with %s", + svc_ident(svc, NULL, 0), svc->conflict); + return 1; + } + compose_cmdline(svc, cmdline, sizeof(cmdline)); if (svc_is_sysv(svc)) logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", cmdline); @@ -1387,7 +1394,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; + char *ready_script = NULL, *conflict = NULL; char *notify = NULL; struct tty tty = { 0 }; char *dev = NULL; @@ -1498,6 +1505,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) cgroup = arg; /* only settings */ else if (MATCH_CMD(cmd, "cgroup.", arg)) cgroup = arg; /* with group */ + else if (MATCH_CMD(cmd, "conflict:", arg)) + conflict = arg; else break; @@ -1696,6 +1705,10 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) strlcpy(svc->file, file, sizeof(svc->file)); else memset(svc->file, 0, sizeof(svc->file)); + if (conflict) + strlcpy(svc->conflict, conflict, sizeof(svc->conflict)); + else + memset(svc->conflict, 0, sizeof(svc->conflict)); svc->manual = manual; svc->respawn = respawn; svc->forking = forking; @@ -2488,6 +2501,9 @@ int service_completed(void) if (!svc_enabled(svc)) continue; + if (svc_conflicts(svc)) + continue; + if (strstr(svc->cond, plugin_hook_str(HOOK_SVC_UP)) || strstr(svc->cond, plugin_hook_str(HOOK_SYSTEM_UP))) { dbg("Skipping %s(%s), post-strap hook", svc->desc, svc_ident(svc, NULL, 0)); diff --git a/src/svc.c b/src/svc.c index be1b63fd..9a2b7dc2 100644 --- a/src/svc.c +++ b/src/svc.c @@ -619,6 +619,51 @@ int svc_enabled(svc_t *svc) return 1; } +/** + * svc_conflicts - Check if svc conflicts with any other running svc + * @svc: + * + * Returns: + * %TRUE(1) or %FALSE(0) + */ +int svc_conflicts(svc_t *svc) +{ + char *ptr, *nm; + int rc = 0; + + if (!svc->conflict[0]) + return 0; + + ptr = strdup(svc->conflict); + if (!ptr) + return 0; + + nm = strtok(ptr, ","); + while (nm) { + char *name, *id; + svc_t *s; + + name = strdupa(nm); + id = strchr(name, ':'); + if (id) + id++ = 0; + else + id = ""; + + s = svc_find(name, id); + if (s) { + if (s->state >= SVC_STOPPING_STATE) + rc = 1; + break; + } + + nm = strtok(NULL, ","); + } + + free(ptr); + return rc; +} + /* break up "job:id job:id job:id ..." into several "job:id" tokens */ static char *tokstr(char *str, size_t len) { diff --git a/src/svc.h b/src/svc.h index c0d33c90..f31f87dc 100644 --- a/src/svc.h +++ b/src/svc.h @@ -181,6 +181,7 @@ typedef struct svc { char cmd[MAX_ARG_LEN]; char args[MAX_NUM_SVC_ARGS][MAX_ARG_LEN]; int args_dirty; + char conflict[MAX_ARG_LEN]; char desc[MAX_STR_LEN]; char env[MAX_ARG_LEN]; char pre_script[MAX_ARG_LEN]; @@ -233,6 +234,7 @@ void svc_prune_bootstrap (void); void svc_enable (svc_t *svc); int svc_enabled (svc_t *svc); +int svc_conflicts (svc_t *svc); int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *));