From 2f957068e567391e7aef5d7a2c075c14c1e6b37a Mon Sep 17 00:00:00 2001 From: turret Date: Fri, 24 Nov 2023 00:57:35 -0600 Subject: misc: subsys upgrade, log timestamps (log) - create LOGLEVEL constant numbers - implement CONSOLE_LOGLEVEL - color array now uses loglevel constants - timestamp now shown (thanks util-linux) (init) - register mainpid - hello world print - fix process reaper to refer to subsys when reaping (subsys) - create maximum subsystem count - create subsystem table - add debugging prints to subsystem entry and termination - create function to handle process termination (unmap stack, free subsystem malloc, clear entry in table) - disable subsystem inception - change die references to fail with print - supply clone with signal to send on termination (SIGCHLD) --- init/subsys.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 8 deletions(-) (limited to 'init/subsys.c') diff --git a/init/subsys.c b/init/subsys.c index 62ee54e..a88046d 100644 --- a/init/subsys.c +++ b/init/subsys.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -13,13 +14,20 @@ #include #define STACK_SIZE 8192 * 512 +#define MAX_SUBSYSTEMS 32 struct subsystem_info { char *fn_name; int (*fn)(void); + int pid; + void *stack; }; -int __subsystem_entry(struct subsystem_info *info) +extern int mainpid; +static struct subsystem_info *subsystems[MAX_SUBSYSTEMS + 1]; +static int subsystem_count = 0; + +static int __subsystem_entry(struct subsystem_info *info) { /* entry point from clone(). we setup the process name so we know what we are looking at from a glance in a ps view or htop or @@ -30,21 +38,51 @@ int __subsystem_entry(struct subsystem_info *info) prctl(PR_SET_NAME, name); free(name); - int ret = info->fn(); + print(LOG_DEBUG "subsys: starting subsystem %s (%d)", info->fn_name, getpid()); - /* we are expected to free info before exiting */ - free(info); + int ret = info->fn(); return ret; } +int subsystem_handle_term(int pid) +{ + for(int i = 0; i < MAX_SUBSYSTEMS; ++i) { + struct subsystem_info *subsystem = subsystems[i]; + if(!subsystem || subsystem->pid != pid) + continue; + + print(LOG_DEBUG "subsys: subsystem terminated %s (%d)", subsystem->fn_name, pid); + + if(munmap(subsystem->stack, STACK_SIZE) < 0) + print(LOG_EMERG "subsys: failed to deallocate stack for subsystem %s (%d) (errno %d)", subsystem->fn_name, pid, errno); + subsystems[i] = 0; + free(subsystem); + + return 0; + } + + return 1; +} + int __impl_start_subsystem(char *fn_name, int (*fn)(void)) { + if(getpid() != mainpid) { + print(LOG_CRIT "subsys: cannot perform subsystem inception (attempted from %d)", getpid()); + return 1; + } + if(subsystem_count >= MAX_SUBSYSTEMS) { + print(LOG_CRIT "subsys: cannot start subsystem %s: reached maximum number of subsystems", fn_name); + return 1; + } + /* because CLONE_VM is being set, our stack is not duplicated and therefore we need to map a stack */ void *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK | MAP_PRIVATE, -1, 0); - if((long)stack < 0) - die("subsys mmap:"); + if((long)stack <= 0) { + print(LOG_CRIT "subsys: cannot start subsystem %s: failed to allocate stack (errno %d)", fn_name, errno); + return 1; + } /* the libc gods have graced us with the ability to pass one (1) arg to the function. struct required. the absence of a free is not a @@ -52,11 +90,23 @@ int __impl_start_subsystem(char *fn_name, int (*fn)(void)) struct subsystem_info *info = malloc(sizeof(struct subsystem_info)); info->fn_name = fn_name; info->fn = fn; + info->stack = stack; - int pid = clone((int (*)(void *))__subsystem_entry, (void *)((long)stack + STACK_SIZE), CLONE_FILES | CLONE_VM, info); + int pid = clone((int (*)(void *))__subsystem_entry, (void *)((long)stack + STACK_SIZE), CLONE_FILES | CLONE_VM | SIGCHLD, info); + info->pid = pid; if(pid < 0) { + print(LOG_CRIT "subsys: cannot start subsystem %s: clone failed (errno %d)", fn_name, errno); munmap(stack, STACK_SIZE); - die("subsys clone:"); + free(info); + return 1; + } + + for(int i = 0; i < MAX_SUBSYSTEMS; ++i) { + if(!subsystems[i]) { + subsystems[i] = info; + ++subsystem_count; + break; + } } return 0; -- cgit v1.2.3