diff options
Diffstat (limited to 'initd/supervisor.c')
-rw-r--r-- | initd/supervisor.c | 242 |
1 files changed, 0 insertions, 242 deletions
diff --git a/initd/supervisor.c b/initd/supervisor.c deleted file mode 100644 index d54b9ca..0000000 --- a/initd/supervisor.c +++ /dev/null @@ -1,242 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -#include "init.h" - -/* service configurations */ -static service_list_t cfg; - -/* service run time data, sorted by target and topological order */ -static svc_run_data_t *rt_data = NULL; -static size_t rt_count = 0; - -/* maps a target to range in rt_data */ -static size_t queue_start[TGT_MAX]; -static size_t queue_count[TGT_MAX]; - -/* current state */ -static size_t queue_idx = 0; -static int target = TGT_BOOT; -static size_t singleshot = 0; - -/*****************************************************************************/ - -static const char *status_str[] = { - [STATE_OFF] = NULL, - [STATE_QUEUED] = NULL, - [STATE_RUNNING] ="\033[22;33m UP \033[0m", - [STATE_COMPLETED] = "\033[22;32mDONE\033[0m", - [STATE_FAILED] ="\033[22;31mFAIL\033[0m", -}; - -static void print_status(const char *msg, int type) -{ - printf("[%s] %s\n", status_str[type], msg); - fflush(stdout); -} - -static void respawn(svc_run_data_t *rt) -{ - if (rt->svc->rspwn_limit > 0) { - rt->rspwn_count += 1; - - if (rt->rspwn_count >= rt->svc->rspwn_limit) - goto fail; - } - - rt->pid = runsvc(rt->svc); - if (rt->pid == -1) - goto fail; - - rt->state = STATE_RUNNING; - return; -fail: - rt->state = STATE_FAILED; - print_status(rt->svc->desc, rt->state); - return; -} - -static void check_target_completion(void) -{ - if (singleshot > 0 || queue_idx < queue_count[target]) - return; - - switch (target) { - case TGT_BOOT: - break; - case TGT_SHUTDOWN: - for (;;) - reboot(RB_POWER_OFF); - break; - case TGT_REBOOT: - for (;;) - reboot(RB_AUTOBOOT); - break; - } -} - -void supervisor_handle_exited(pid_t pid, int status) -{ - svc_run_data_t *rt; - service_t *svc; - size_t i; - - for (i = 0; i < rt_count; ++i) { - if (rt_data[i].pid == pid) - break; - } - - if (i >= rt_count) - return; - - rt = rt_data + i; - svc = rt->svc; - rt->status = status; - rt->pid = -1; - - if (svc->type == SVC_RESPAWN) { - if (target != TGT_REBOOT && target != TGT_SHUTDOWN) - respawn(rt); - } else { - if (rt->status == EXIT_SUCCESS) { - rt->state = STATE_COMPLETED; - } else { - rt->state = STATE_FAILED; - } - - print_status(svc->desc, rt->state); - - if (svc->type == SVC_ONCE) - singleshot -= 1; - - check_target_completion(); - } -} - -void supervisor_set_target(int next) -{ - if (target == TGT_REBOOT || target == TGT_SHUTDOWN || next == target) - return; - - if (queue_idx < queue_count[target]) { - if (next != TGT_REBOOT && next != TGT_SHUTDOWN) - return; - } - - target = next; - queue_idx = 0; -} - -void supervisor_init(void) -{ - int status = STATE_FAILED; - service_t *it; - size_t i, j; - - if (svcscan(SVCDIR, &cfg)) - goto out; - - /* allocate run time data */ - rt_count = 0; - - for (i = 0; i < TGT_MAX; ++i) { - for (it = cfg.targets[i]; it != NULL; it = it->next) - ++rt_count; - } - - rt_data = calloc(rt_count, sizeof(rt_data[0])); - if (rt_data == NULL) { - rt_count = 0; - goto out; - } - - /* map runtime data to services */ - j = 0; - - for (i = 0; i < TGT_MAX; ++i) { - queue_start[i] = j; - - for (it = cfg.targets[i]; it != NULL; it = it->next) { - rt_data[j].svc = it; - rt_data[j].state = STATE_OFF; - rt_data[j].pid = -1; - ++j; - } - - queue_count[i] = j - queue_start[i]; - } - - /* initialize state */ - status = STATE_COMPLETED; - - for (i = 0; i < queue_count[target]; ++i) - rt_data[queue_start[target] + i].state = STATE_QUEUED; -out: - print_status("reading configuration from " SVCDIR, status); -} - -static pid_t wait_for_process(int *status) -{ - pid_t pid = wait(status); - - if (pid == -1 || !WIFEXITED(*status)) { - *status = EXIT_FAILURE; - } else { - *status = WEXITSTATUS(*status); - } - return pid; -} - -void supervisor_process_queues(void) -{ - svc_run_data_t *rt; - service_t *svc; - size_t count; - int status; - pid_t pid; - - count = queue_count[target]; - - if (queue_idx >= count) { - pid = wait_for_process(&status); - supervisor_handle_exited(pid, status); - return; - } - - rt = rt_data + queue_start[target] + queue_idx++; - svc = rt->svc; - - if (svc->flags & SVC_FLAG_HAS_EXEC) { - rt->pid = runsvc(rt->svc); - - if (rt->pid == -1) { - rt->state = STATE_FAILED; - print_status(svc->desc, rt->state); - } else { - rt->state = STATE_RUNNING; - print_status(svc->desc, rt->state); - - switch (svc->type) { - case SVC_WAIT: - for (;;) { - pid = wait_for_process(&status); - if (pid == rt->pid) - break; - supervisor_handle_exited(pid, status); - } - - rt->state = status == EXIT_SUCCESS ? - STATE_COMPLETED : STATE_FAILED; - print_status(svc->desc, rt->state); - break; - case SVC_ONCE: - singleshot += 1; - break; - } - } - } else { - rt->status = EXIT_SUCCESS; - rt->state = STATE_COMPLETED; - print_status(svc->desc, rt->state); - } - - check_target_completion(); -} |