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) --- include/log.h | 12 +++++++++++ init/init.c | 26 ++++++++++++++++------- init/log.c | 33 +++++++++++++++++++++--------- init/subsys.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 112 insertions(+), 25 deletions(-) diff --git a/include/log.h b/include/log.h index 52d45ff..397ce2b 100644 --- a/include/log.h +++ b/include/log.h @@ -2,6 +2,18 @@ #define LOG_SOH "\001" #define LOG_SOH_ASCII '\001' +#define EMERG_LOGLEVEL 0 +#define ALERT_LOGLEVEL 1 +#define CRIT_LOGLEVEL 2 +#define ERR_LOGLEVEL 3 +#define WARNING_LOGLEVEL 4 +#define NOTICE_LOGLEVEL 5 +#define INFO_LOGLEVEL 6 +#define DEBUG_LOGLEVEL 7 + +#define DEFAULT_LOGLEVEL NOTICE_LOGLEVEL +#define CONSOLE_LOGLEVEL DEBUG_LOGLEVEL + #define LOG_EMERG LOG_SOH "0" #define LOG_ALERT LOG_SOH "1" #define LOG_CRIT LOG_SOH "2" diff --git a/init/init.c b/init/init.c index 7c2d6a6..97461ef 100644 --- a/init/init.c +++ b/init/init.c @@ -1,9 +1,14 @@ #include #include +#include #include +#include #include +extern int subsystem_handle_term(int pid); +int mainpid = 0; + /* For some reason, I get SIGSEGV'd when running because a random-ass byte was inserted where it isnt supposed to be. Added a safety byte because I cannot be asked to try to figure out how to do this cleanly. */ @@ -48,20 +53,27 @@ static void do_initcalls(void) int main(void) { + print("init: Hello world! Running " NAME " v" VERSION "!"); + + mainpid = getpid(); + + /* Rest of the program.. */ do_initcalls(); /* Reaper. Much like init. */ - // BUG: doesnt actually work?? we have defunct processes still - // TODO: fix bug + siginfo_t siginfo; static sigset_t set; sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, NULL); while(1) { - int sig; - sigwait(&set, &sig); - if(sig == SIGCHLD) - while(waitpid(0, NULL, WNOHANG) > 0) - ; + sigwaitinfo(&set, &siginfo); + int sig = siginfo.si_signo; + if(sig == SIGCHLD) { + int process = 0; + while((process = waitpid(-1, NULL, WNOHANG)) > 0) + if(subsystem_handle_term(process) > 0) + print("init: failed to reap process %d", process); + } } } diff --git a/init/log.c b/init/log.c index d3bcbe4..eb2cd09 100644 --- a/init/log.c +++ b/init/log.c @@ -2,32 +2,38 @@ #include #include #include +#include #include #include #include static const char *colors[] = { - [0] = ANSI_BLINK ANSI_REVERSE ANSI_BOLD ANSI_RED, - [1] = ANSI_REVERSE ANSI_BOLD ANSI_RED, - [2] = ANSI_BOLD ANSI_RED, - [3] = ANSI_RED, - [4] = ANSI_BOLD, - [5] = ANSI_BRIGHT_WHITE, - [6] = ANSI_RESET, - [7] = ANSI_ITALIC ANSI_BRIGHT_BLUE, + [EMERG_LOGLEVEL] = ANSI_BLINK ANSI_REVERSE ANSI_BOLD ANSI_RED, + [ALERT_LOGLEVEL] = ANSI_REVERSE ANSI_BOLD ANSI_RED, + [CRIT_LOGLEVEL] = ANSI_BOLD ANSI_RED, + [ERR_LOGLEVEL] = ANSI_RED, + [WARNING_LOGLEVEL] = ANSI_BOLD, + [NOTICE_LOGLEVEL] = ANSI_BRIGHT_WHITE, + [INFO_LOGLEVEL] = ANSI_RESET, + [DEBUG_LOGLEVEL] = ANSI_ITALIC ANSI_BRIGHT_BLUE, }; +int start_time = 0; int console_lock = 0; int print(const char *fmt, ...) { - int loglevel = 5; + int loglevel = DEFAULT_LOGLEVEL; if(fmt[0] == LOG_SOH_ASCII) { loglevel = (fmt[1] - 0x30) % 10; fmt += 2; } + /* not going to be printed? dont bother! */ + if(loglevel > CONSOLE_LOGLEVEL) + return 0; + /* we essentially print the user's raw input to its own buffer, later we will parse it and print out ANSI colors and what not */ char buf[512]; @@ -44,6 +50,11 @@ int print(const char *fmt, ...) break; } + char tsbuf[64] = "\0"; + struct timeval time; + gettimeofday(&time, NULL); + snprintf(tsbuf, sizeof(tsbuf), "[%5ld.%06ld] ", (long)time.tv_sec % 100000, (long)time.tv_usec); + /* spin lock, at the cost of architecture portability concurrency is something that we need to adjust for, and the console will be scrambled and unreadable if we allow writing all @@ -58,8 +69,10 @@ int print(const char *fmt, ...) /* we want to support stuff without colons, but frankly I havent tested this at time of writing. will find out later */ + writeputs(ANSI_RESET ANSI_GREEN); + writeputs(tsbuf); + writeputs(ANSI_RESET); if(buf[colon] == ':') { - writeputs(ANSI_RESET); writeputs(colors[loglevel]); writeputs(ANSI_YELLOW); write(STDOUT_FILENO, buf, colon); 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