From 3c015f384d3a34034c618bbdbdb392c140805b0d Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Wed, 13 Dec 2017 17:24:06 +0100 Subject: [PATCH] Track run/tasks, should run at least once per declared runlevel This patch adds a 'once' counter to the svc_t for run/task jobs. This counter is incremented when Finit calls service_start() and is reset on runlevel changes. Also, at the end of a runlevel each run/task have their state reset to SVC_HALTED_STATE so they can be launched again for the new runlevel, if so declared. Signed-off-by: Joachim Nilsson --- src/service.c | 25 ++++++++++++++++++++++++- src/service.h | 1 + src/sm.c | 3 +++ src/svc.h | 4 +++- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 36ac8721..aa4be3b7 100644 --- a/src/service.c +++ b/src/service.c @@ -274,7 +274,7 @@ static int service_start(svc_t *svc) if (svc->inetd.cmd) status = svc->inetd.cmd(svc->inetd.type); - else if (svc->type & SVC_TYPE_RUNTASK) + else if (svc_is_runtask(svc)) status = exec_runtask(svc->cmd, args); else status = execv(svc->cmd, args); @@ -920,6 +920,11 @@ restart: svc_set_state(svc, SVC_STOPPING_STATE); break; } + + if (svc_is_runtask(svc)) { + svc->once++; + break; + } } cond = cond_get_agg(svc->cond); @@ -995,6 +1000,24 @@ void service_step_all(int types) svc_foreach_type(types, service_step); } +/** + * svc_clean_runtask - Clear once flag of runtasks + * + * XXX: runtasks should be stopped before calling this + */ +void service_runtask_clean(void) +{ + svc_t *svc; + + for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { + if (!svc_is_runtask(svc)) + continue; + svc->once = 0; + if (svc->state == SVC_DONE_STATE) + svc_set_state(svc, SVC_HALTED_STATE); + } +} + /** * Local Variables: * indent-tabs-mode: t diff --git a/src/service.h b/src/service.h index d907846f..c486ab29 100644 --- a/src/service.h +++ b/src/service.h @@ -31,6 +31,7 @@ void service_runlevel (int newlevel); int service_register (int type, char *line, struct rlimit rlimit[], struct timeval *mtime); void service_unregister (svc_t *svc); +void service_runtask_clean (void); void service_reload_dynamic (void); void service_step (svc_t *svc); diff --git a/src/sm.c b/src/sm.c index 7bc8a8d4..4d90a941 100644 --- a/src/sm.c +++ b/src/sm.c @@ -145,6 +145,9 @@ restart: if (runlevel != 0 && runlevel != 6) conf_reload_dynamic(); + /* Reset once flag of runtasks */ + service_runtask_clean(); + _d("Stopping services services not allowed in new runlevel ..."); sm->in_teardown = 1; service_step_all(SVC_TYPE_ANY); diff --git a/src/svc.h b/src/svc.h index 640fbf50..e4c19b4c 100644 --- a/src/svc.h +++ b/src/svc.h @@ -91,7 +91,7 @@ typedef struct svc { /* Service details */ pid_t pid; const svc_state_t state; /* Paused, Reloading, Restart, Running, ... */ - svc_type_t type; + svc_type_t type; /* Service, run, task, inetd, ... */ struct timeval mtime; /* Modification time for .conf from /etc/finit.d/ */ const int dirty; /* Set if old mtime != new mtime => reloaded, * or -1 when marked for removal */ @@ -102,6 +102,7 @@ typedef struct svc { char cond[MAX_COND_LEN]; /* Counters */ + char once; /* run/task, (at least) once per runlevel */ const char restart_cnt; /* Incremented for each restart by service monitor. */ /* For inetd services */ @@ -196,6 +197,7 @@ static inline int svc_is_updated (svc_t *svc) { return svc && 1 == svc->dirty static inline int svc_is_inetd (svc_t *svc) { return svc && SVC_TYPE_INETD == svc->type; } static inline int svc_is_inetd_conn(svc_t *svc) { return svc && SVC_TYPE_INETD_CONN == svc->type; } static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; } +static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type); } static inline int svc_is_blocked (svc_t *svc) { return svc->block != SVC_BLOCK_NONE; } static inline int svc_is_busy (svc_t *svc) { return svc->block == SVC_BLOCK_BUSY; }