From 51befb492cf12a0e21b47ef3cc8ee8c9b5aaadb3 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 15 May 2023 14:18:22 +0200 Subject: [PATCH] Allow conflicting services to start when conflict is resolved These changes add a new svc_block_t type: SVC_BLOCK_CONFLICT so a user can more clearly see why a run/task/service has not been started by Finit. The reason for the block is by default logged, which can be escaped by using the `nowarn` flag. Also, when the conflict is resolved, allow the service to start. With these changes, the system/hotplug.conf should work better and cause less questions about "strange" log messages. Signed-off-by: Joachim Wiberg --- src/api.c | 2 ++ src/service.c | 27 ++++++++++++++++++++------- src/svc.h | 7 +++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/api.c b/src/api.c index 0485a461..7bcc8ffc 100644 --- a/src/api.c +++ b/src/api.c @@ -65,6 +65,7 @@ static int stop(svc_t *svc, void *user_data) service_timeout_cancel(svc); svc_stop(svc); service_step(svc); + service_step_all(SVC_TYPE_ANY); return 0; } @@ -77,6 +78,7 @@ static int start(svc_t *svc, void *user_data) service_timeout_cancel(svc); svc_start(svc); service_step(svc); + service_step_all(SVC_TYPE_ANY); return 0; } diff --git a/src/service.c b/src/service.c index f0d28e41..21acd287 100644 --- a/src/service.c +++ b/src/service.c @@ -610,13 +610,6 @@ 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); @@ -1737,6 +1730,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) else memset(svc->ifstmt, 0, sizeof(svc->ifstmt)); svc->manual = manual; + svc->nowarn = nowarn; svc->respawn = respawn; svc->forking = forking; svc->restart_max = restart_max; @@ -2276,6 +2270,15 @@ restart: case SVC_HALTED_STATE: if (enabled) svc_set_state(svc, SVC_WAITING_STATE); + else { + if (svc_is_conflict(svc)) { + logit(svc->nowarn ? LOG_DEBUG : LOG_INFO, + "%s in conflict with %s, checking again ...", + svc_ident(svc, NULL, 0), svc->conflict); + if (!svc_conflicts(svc)) + svc_unblock(svc); + } + } break; case SVC_DONE_STATE: @@ -2342,6 +2345,16 @@ restart: if (sm_is_in_teardown(&sm)) break; + /* Don't start if it conflicts with something else already started */ + if (svc_conflicts(svc)) { + logit(svc->nowarn ? LOG_DEBUG : LOG_INFO, + "Not starting %s, conflicts with %s", + svc_ident(svc, NULL, 0), svc->conflict); + svc_conflict(svc); + svc_set_state(svc, SVC_HALTED_STATE); + break; + } + if (svc_has_pre(svc)) { svc_set_state(svc, SVC_SETUP_STATE); service_pre_script(svc); diff --git a/src/svc.h b/src/svc.h index 9a9eb440..c5cddca5 100644 --- a/src/svc.h +++ b/src/svc.h @@ -74,6 +74,7 @@ typedef enum { SVC_BLOCK_USER, SVC_BLOCK_BUSY, SVC_BLOCK_RESTARTING, + SVC_BLOCK_CONFLICT, } svc_block_t; typedef enum { @@ -125,6 +126,7 @@ typedef struct svc { svc_type_t type; /* Service, run, task, ... */ char protect; /* Services like dbus-daemon & udev by Finit */ char manual; /* run/task that require `initctl start foo` */ + char nowarn; /* Skip or log warning if cmd missing or conflicts */ const int dirty; /* 0: unmodified, 1: modified */ const int removed; int starting; /* ... waiting for pidfile to be re-asserted */ @@ -270,6 +272,7 @@ static inline int svc_is_busy (svc_t *svc) { return svc && svc->block == SV static inline int svc_is_missing (svc_t *svc) { return svc && svc->block == SVC_BLOCK_MISSING; } static inline int svc_is_crashing (svc_t *svc) { return svc && svc->block == SVC_BLOCK_CRASHING; } static inline int svc_is_restart (svc_t *svc) { return svc && svc->block == SVC_BLOCK_RESTARTING; } +static inline int svc_is_conflict (svc_t *svc) { return svc && svc->block == SVC_BLOCK_CONFLICT; } static inline void svc_unblock (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_NONE; } #define svc_start(svc) svc_unblock(svc) @@ -278,6 +281,7 @@ static inline void svc_busy (svc_t *svc) { if (svc) svc->block = SVC_BLOC static inline void svc_missing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_MISSING; } static inline void svc_restarting (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_RESTARTING; } static inline void svc_crashing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CRASHING; } +static inline void svc_conflict (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CONFLICT; } /* Has condition in configuration and cond is allowed? */ static inline int svc_has_cond(svc_t *svc) @@ -350,6 +354,9 @@ static inline char *svc_status(svc_t *svc) case SVC_BLOCK_RESTARTING: return "restart"; + case SVC_BLOCK_CONFLICT: + return "conflict"; + } return "unknown";