Fix #129: add pre:script and post:script action support

This patch updates the service state machine with two new states: SETUP
and CLEANUP.  If an executable pre:/path/to/script is defined for a
service, it is called every time the task goes to READY state.  If an
executable post:/path/to/script is defined for a service, it is called
when the task goes to HALTED state.

Each of these two scripts default to a three (3) second execution time
before they are SIGKILLed.  This can be adjusted with the `kill:SEC`
option for the service.  There are no execution guarantees, nor are
there any way of detecting if the script was killed before completion or
not -- except for running Finit in debug mode and inspecting the result
printed by system_monitor().

Note: the post:script MUST be idempotent since transitions between READY
      and HALTED can take place any number of times before a task goes
      to its RUNNING state.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2021-04-18 11:33:38 +02:00
1 parent 9fd860ef3c
commit ba858743e5
3 files changed
+192 -46

No files matched your search

+12
View File
@@ -54,6 +54,8 @@ typedef enum {
SVC_HALTED_STATE = 0, /* Not allowed in runlevel, or not enabled. */
SVC_DONE_STATE, /* Task/Run job has been run */
SVC_STOPPING_STATE, /* Waiting to collect the child process */
SVC_CLEANUP_STATE, /* Running post: script */
SVC_SETUP_STATE, /* Running pre: script */
SVC_WAITING_STATE, /* Condition is in flux, process SIGSTOPed */
SVC_READY_STATE, /* Enabled but condition not satisfied */
SVC_RUNNING_STATE, /* Process running */
@@ -160,6 +162,8 @@ typedef struct svc {
int args_dirty;
char desc[MAX_STR_LEN];
char env[MAX_ARG_LEN];
char pre_script[MAX_ARG_LEN];
char post_script[MAX_ARG_LEN];
/*
* Used to forcefully kill services that won't shutdown on
@@ -214,6 +218,8 @@ static inline int svc_is_forking (svc_t *svc) { return (svc_is_daemon(svc) ||
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sighup || 0 != svc->args_dirty); }
static inline int svc_has_pidfile (svc_t *svc) { return svc_is_daemon(svc) && svc->pidfile[0] != 0 && svc->pidfile[0] != '!'; }
static inline int svc_has_pre (svc_t *svc) { return svc->pre_script[0]; }
static inline int svc_has_post (svc_t *svc) { return svc->post_script[0]; }
static inline void svc_starting (svc_t *svc) { if (svc) svc->starting = 1; }
static inline void svc_started (svc_t *svc) { if (svc) svc->starting = 0; }
@@ -301,6 +307,12 @@ static inline char *svc_status(svc_t *svc)
case SVC_WAITING_STATE:
return "waiting";
case SVC_CLEANUP_STATE:
return "cleanup";
case SVC_SETUP_STATE:
return "setup";
case SVC_READY_STATE:
return "ready";