aboutsummaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorturret <turret@duck.com>2023-11-24 00:57:35 -0600
committerturret <turret@duck.com>2023-11-24 00:57:35 -0600
commit2f957068e567391e7aef5d7a2c075c14c1e6b37a (patch)
tree2e58f3008886e3372ebb26d1d7ae83a3ac0adae5 /init
parent40bff7788865b519b79b1ee7eb9851914010ffb4 (diff)
downloaddiscord-bot-skeleton-2f957068e567391e7aef5d7a2c075c14c1e6b37a.tar.gz
discord-bot-skeleton-2f957068e567391e7aef5d7a2c075c14c1e6b37a.tar.bz2
discord-bot-skeleton-2f957068e567391e7aef5d7a2c075c14c1e6b37a.zip
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)
Diffstat (limited to 'init')
-rw-r--r--init/init.c26
-rw-r--r--init/log.c33
-rw-r--r--init/subsys.c66
3 files changed, 100 insertions, 25 deletions
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 <signal.h>
#include <sys/wait.h>
+#include <config.h>
#include <init.h>
+#include <log.h>
#include <util.h>
+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 <stdio.h>
#include <string.h>
#include <sys/file.h>
+#include <sys/time.h>
#include <unistd.h>
#include <log.h>
#include <util.h>
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 <errno.h>
#include <sched.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -13,13 +14,20 @@
#include <util.h>
#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;