From 2cfc263daec3776090be87b69688dfeeea2fbacd Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 13 May 2020 17:55:45 +0200 Subject: Move rest of initd supervisor code into main.c Signed-off-by: David Oberhollenzer --- initd/Makemodule.am | 1 - initd/init.h | 10 --- initd/main.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++ initd/supervisor.c | 242 ---------------------------------------------------- 4 files changed, 240 insertions(+), 253 deletions(-) delete mode 100644 initd/supervisor.c diff --git a/initd/Makemodule.am b/initd/Makemodule.am index 294b2ee..9f4b872 100644 --- a/initd/Makemodule.am +++ b/initd/Makemodule.am @@ -1,5 +1,4 @@ init_SOURCES = initd/main.c initd/init.h initd/runsvc.c -init_SOURCES += initd/supervisor.c init_CPPFLAGS = $(AM_CPPFLAGS) init_CFLAGS = $(AM_CFLAGS) init_LDFLAGS = $(AM_LDFLAGS) diff --git a/initd/init.h b/initd/init.h index bfc1f62..2c2adb1 100644 --- a/initd/init.h +++ b/initd/init.h @@ -54,14 +54,4 @@ typedef struct { */ pid_t runsvc(service_t *svc); -/********** supervisor.c **********/ - -void supervisor_handle_exited(pid_t pid, int status); - -void supervisor_set_target(int next); - -void supervisor_init(void); - -void supervisor_process_queues(void); - #endif /* INIT_H */ diff --git a/initd/main.c b/initd/main.c index 446553c..e40fc32 100644 --- a/initd/main.c +++ b/initd/main.c @@ -1,6 +1,246 @@ /* 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; + } +} + +static 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(); + } +} + +static 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; +} + +static 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; +} + +static 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(); +} + static void handle_signal(int signo) { switch (signo) { 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(); -} -- cgit v1.2.3