Added sync() system call for testing purposes. Added SIGSTP signal handler. Removed CtrlCException. Added dummy SIGCHLD handler for future process reaping. NimD now creates some symlinks at startup so Linux ports of BSD software don't crash. Moved exists procedure to misc module. UnmountAllDisks now unmounts the source instead of the target. Other minor fixes and typos

This commit is contained in:
Nocturn9x 2021-12-02 23:16:16 +01:00
parent 6ef157baa0
commit bd7d4e1974
6 changed files with 70 additions and 19 deletions

View File

@ -0,0 +1,3 @@
.git
nimd
src/main

View File

@ -6,6 +6,7 @@ WORKDIR /code
# Removes any already existing binary so that when compilation fails the container stops
RUN rm -f /code/nimd
RUN rm -f /code/main
RUN nimble install syscall -y
RUN nim -d:release --opt:size --passL:"-static" --gc:orc -d:useMalloc c -o:nimd src/main
RUN cp /code/nimd /sbin/nimd

View File

@ -35,8 +35,12 @@ proc mainLoop*(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fs
logger.fatal(&"A fatal error has occurred while preparing filesystem, booting cannot continue. Error -> {getCurrentExceptionMsg()}")
nimDExit(logger, 131)
logger.info("Disks mounted")
logger.debug("Calling sync() just in case")
doSync(logger)
logger.info("Setting hostname")
logger.debug(&"Hostname was set to '{setHostname(logger)}'")
logger.info("Creating symlinks")
createSymlinks(logger)
logger.info("Processing boot runlevel")
# TODO
logger.info("Processing default runlevel")
@ -46,9 +50,6 @@ proc mainLoop*(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fs
try:
# TODO
sleepSeconds(5)
except CtrlCException:
logger.warning("Main process received SIGINT: exiting") # TODO: Ignore this once we stop testing on our local machines lol
nimDExit(logger, 130, emerg=false) # 130 - Interrupted by SIGINT
except:
logger.critical(&"A critical error has occurred while running, restarting the mainloop! Error -> {getCurrentExceptionMsg()}")
# We *absolutely* cannot die

View File

@ -37,11 +37,14 @@ proc main(logger: Logger) =
logger.fatal(&"NimD must run as root, but current user id is {uid}")
quit(EPERM) # EPERM - Operation not permitted
logger.debug("Setting up dummy signal handlers")
onSignal(SIGABRT, SIGALRM, SIGHUP, SIGILL, SIGKILL, SIGQUIT, SIGSTOP, SIGSEGV,
onSignal(SIGABRT, SIGALRM, SIGHUP, SIGILL, SIGKILL, SIGQUIT, SIGSTOP, SIGSEGV, SIGTSTP,
SIGTRAP, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, 6, SIGFPE, SIGBUS, SIGURG, SIGINT): # 6 is SIGIOT
# Can't capture local variables because this implicitly generates
# a noconv procedure
getDefaultLogger().warning(&"Ignoring signal {sig} ({strsignal(sig)})") # Nim injects the variable "sig" into the scope. Gotta love those macros
logger.debug("Setting up SIGCHLD signal handler")
onSignal(SIGCHLD):
reapProcess(getDefaultLogger())
logger.debug("Starting uninterruptible mainloop")
mainLoop(logger)

View File

@ -115,16 +115,6 @@ proc umount*(target: string): int = int(umount(cstring(target)))
proc umount2*(target: string, flags: int): int = int(umount2(cstring(target), cint(flags)))
proc exists(p: string): bool =
# Checks if a path exists. Thanks
# araq :)
try:
discard getFileInfo(p)
result = true
except OSError:
result = false
proc checkDisksIsMounted(search: tuple[source, target, filesystemtype: string, mountflags: uint64, data: string, dump, pass: uint8], expand: bool = false): bool =
## Returns true if a disk is already mounted. If expand is true,
## symlinks are expanded and checked instead of doing a simple
@ -211,9 +201,9 @@ proc unmountAllDisks*(logger: Logger, code: int) =
logger.debug(&"Skipping unmounting filesystem {entry.source} ({entry.filesystemtype}) from {entry.target}: not mounted")
continue
logger.debug(&"Unmounting filesystem {entry.source} ({entry.filesystemtype}) from {entry.target}")
logger.trace(&"Calling umount2('{entry.target}', MNT_DETACH)")
retcode = umount2(entry.target, 2) # 2 = MNT_DETACH - Since we're shutting down, we need the disks to be *gone*!
logger.trace(&"umount2('{entry.target}', MNT_DETACH) returned {retcode}")
logger.trace(&"Calling umount2('{entry.source}', MNT_DETACH)")
retcode = umount2(entry.source, 2) # 2 = MNT_DETACH - Since we're shutting down, we need the disks to be *gone*!
logger.trace(&"umount2('{entry.source}', MNT_DETACH) returned {retcode}")
if retcode == -1:
logger.error(&"Unmounting disk {entry.source} from {entry.target} has failed with error {posix.errno}: {posix.strerror(posix.errno)}")
# Resets the error code

View File

@ -17,16 +17,45 @@
import os
import strformat
import strutils
import syscall
import logging
type CtrlCException* = object of CatchableError
# Note: This will work reliably only with absolute paths. Use with care
const symlinks: array[7, tuple[dest, source: string]] = [
(dest: "/dev/fd", source: "/proc/self/fd"),
(dest: "/dev/fd/0", source: "/proc/self/fd/0"),
(dest: "/dev/fd/1", source: "/proc/self/fd/1"),
(dest: "/dev/fd/2", source: "/proc/self/fd/2"),
(dest: "/dev/std/in", source: "/proc/self/fd/0"),
(dest: "/dev/std/out", source: "/proc/self/fd/1"),
(dest: "/dev/std/err", source: "/proc/self/fd/2"),
]
var shutdownHandlers: seq[proc (logger: Logger, code: int)] = @[]
proc doSync*(logger: Logger) =
logger.debug(&"Calling sync() syscall has returned {syscall(SYNC)}")
proc reapProcess*(logger: Logger) =
logger.debug("Handling SIGCHLD")
# TODO
proc exists*(p: string): bool =
# Checks if a path exists. Thanks
# araq :)
try:
discard getFileInfo(p)
result = true
except OSError:
result = false
proc addShutdownHandler*(handler: proc (logger: Logger, code: int), logger: Logger) =
shutdownHandlers.add(handler)
@ -83,7 +112,31 @@ proc setHostname*(logger: Logger): string =
return hostname
proc createSymlinks*(logger: Logger) =
## Creates a set of symlinks needed
## by stuff like Linux ports of BSD
## software
for sym in symlinks:
try:
if not exists(sym.source):
logger.warning(&"Skipping creation of symbolic link from {sym.dest} to {sym.source}: destination does not exist")
continue
elif exists(sym.dest):
if symlinkExists(sym.dest) and sameFile(expandSymlink(sym.dest), sym.source):
logger.debug(&"Skipping creation of symbolic link from {sym.dest} to {sym.source}: link already exists")
elif symlinkExists(sym.dest) and not sameFile(expandSymlink(sym.dest), sym.source):
logger.warning(&"Attempted to create symbolic link from {sym.dest} to {sym.source}, but link already exists and points to {expandSymlink(sym.dest)}")
continue
logger.debug(&"Creating symbolic link from {sym.source} to {sym.dest}")
createSymlink(sym.dest, sym.source)
except:
logger.error(&"Failed to create symbolic link from {sym.dest} to {sym.source}: {getCurrentExceptionMsg()}")
proc createDirectories*(logger: Logger) =
## Creates
proc sleepSeconds*(amount: SomeInteger) = sleep(amount * 1000)
proc strsignal*(sig: cint): cstring {.header:"string.h", importc.}
proc strsignal*(sig: cint): cstring {.header: "string.h", importc.}