aboutsummaryrefslogtreecommitdiff
path: root/initd/supervisor.c
diff options
context:
space:
mode:
Diffstat (limited to 'initd/supervisor.c')
-rw-r--r--initd/supervisor.c242
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();
-}