mirror of https://github.com/nocturn9x/nimd.git
Fixed issues with fcntl and replaced file locking with a duplicate of stderr in O_APPEND mode. Added basic utilities for shutdown/reboot/halt
This commit is contained in:
parent
a93c3c6fd0
commit
d41e67f413
|
@ -23,12 +23,13 @@ import shutdown
|
|||
|
||||
|
||||
|
||||
proc mainLoop*(logger: Logger, workers: int = 1) =
|
||||
proc mainLoop*(logger: Logger, workers: int = 1, startServices: bool = true) =
|
||||
## NimD's main execution loop
|
||||
logger.info("Processing default runlevel")
|
||||
startServices(logger, workers=workers, level=Default)
|
||||
logger.debug(&"Unblocking signals")
|
||||
unblockSignals(logger)
|
||||
if startServices:
|
||||
logger.info("Processing default runlevel")
|
||||
startServices(logger, workers=workers, level=Default)
|
||||
logger.debug(&"Unblocking signals")
|
||||
unblockSignals(logger)
|
||||
logger.info("System initialization complete, idling on control socket")
|
||||
var opType: string
|
||||
try:
|
||||
|
@ -37,10 +38,12 @@ proc mainLoop*(logger: Logger, workers: int = 1) =
|
|||
serverSocket.listen(5)
|
||||
var clientSocket = newSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
|
||||
logger.switchToFile()
|
||||
logger.debug("Entering accept() loop")
|
||||
while true:
|
||||
serverSocket.accept(clientSocket)
|
||||
logger.debug(&"Received connection on control socket")
|
||||
if clientSocket.recv(opType, size=1) == 0:
|
||||
logger.debug(&"Client has disconnected, waiting for new connection")
|
||||
logger.debug(&"Client has disconnected, waiting for new connections")
|
||||
continue
|
||||
logger.debug(&"Received operation type '{opType}' via control socket")
|
||||
# The operation type is a single byte:
|
||||
|
@ -68,4 +71,4 @@ proc mainLoop*(logger: Logger, workers: int = 1) =
|
|||
logger.critical(&"A critical error has occurred while running, restarting the mainloop in 30 seconds! Error -> {getCurrentExceptionMsg()}")
|
||||
sleepSeconds(30)
|
||||
# We *absolutely* cannot die
|
||||
mainLoop(logger)
|
||||
mainLoop(logger, startServices=false)
|
||||
|
|
|
@ -31,7 +31,7 @@ type ShutdownHandler* = ref object
|
|||
body*: proc (logger: Logger, code: int)
|
||||
|
||||
|
||||
const reboot_codes = {"poweroff": 0x4321fedc'i64, "restart": 0x01234567'i64, "halt": 0xcdef0123}.toTable()
|
||||
const reboot_codes = {"poweroff": 0x4321fedc'i64, "reboot": 0x01234567'i64, "halt": 0xcdef0123}.toTable()
|
||||
|
||||
|
||||
proc newShutdownHandler*(body: proc (logger: Logger, code: int)): ShutdownHandler =
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright 2021 Mattia Giambirtone & All Contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import net
|
||||
|
||||
|
||||
when isMainModule:
|
||||
var sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
|
||||
try:
|
||||
sock.connectUnix("/var/run/nimd.sock")
|
||||
except OSError:
|
||||
echo getCurrentExceptionMsg()
|
||||
quit(-1)
|
||||
echo sock.trySend("r")
|
||||
sock.close()
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright 2021 Mattia Giambirtone & All Contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import net
|
||||
|
||||
|
||||
when isMainModule:
|
||||
var sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
|
||||
try:
|
||||
sock.connectUnix("/var/run/nimd.sock")
|
||||
except OSError:
|
||||
echo getCurrentExceptionMsg()
|
||||
quit(-1)
|
||||
echo sock.trySend("p")
|
||||
sock.close()
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright 2021 Mattia Giambirtone & All Contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import net
|
||||
|
||||
|
||||
when isMainModule:
|
||||
var sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
|
||||
try:
|
||||
sock.connectUnix("/var/run/nimd.sock")
|
||||
except OSError:
|
||||
echo getCurrentExceptionMsg()
|
||||
quit(-1)
|
||||
echo sock.trySend("r")
|
||||
sock.close()
|
|
@ -38,10 +38,21 @@ type
|
|||
level*: LogLevel
|
||||
handlers*: seq[LogHandler]
|
||||
|
||||
|
||||
proc dup3(a1, a2, a3: cint): cint {.importc.}
|
||||
|
||||
|
||||
var defaultLevel = LogLevel.Info
|
||||
var logFile = "/var/log/nimd"
|
||||
var logToFileOnly: bool = false
|
||||
|
||||
## This mess is needed to make sure stderr writes are mostly atomic. Sort of
|
||||
## No error handling yet. Deal with it
|
||||
var customStderrFd = dup(stderr.getFileHandle())
|
||||
discard dup3(stderr.getFileHandle(), customStderrFd, O_APPEND)
|
||||
var customStderr: File
|
||||
discard open(customStderr, customStderrFd, fmAppend)
|
||||
|
||||
|
||||
proc log(self: Logger, level: LogLevel = defaultLevel, message: string) # Forward declaration
|
||||
|
||||
|
@ -79,132 +90,91 @@ proc log(self: Logger, level: LogLevel = defaultLevel, message: string) =
|
|||
# Do NOT touch the alignment offsets or your console output and logs will look like trash
|
||||
|
||||
|
||||
proc lockFile(logger: Logger, handle: File) =
|
||||
## Locks the given file across the whole system for writing using fcntl()
|
||||
if fcntl(handle.getFileHandle(), F_WRLCK) == -1:
|
||||
setForegroundColor(fgRed)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} ERROR {"-":>3} ({posix.getpid():03})] Error while locking handle (code {posix.errno}, {posix.strerror(posix.errno)}): output may be mangled""")
|
||||
setForegroundColor(fgDefault)
|
||||
|
||||
|
||||
proc unlockFile(logger: Logger, handle: File) =
|
||||
## Unlocks the given file across the whole system for writing using fcntl()
|
||||
if fcntl(handle.getFileHandle(), F_UNLCK) == -1:
|
||||
setForegroundColor(fgRed)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} ERROR {"-":>3} ({posix.getpid():03})] Error while unlocking handle (code {posix.errno}, {posix.strerror(posix.errno)}): output may be missing""")
|
||||
setForegroundColor(fgDefault)
|
||||
|
||||
|
||||
proc logTraceStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgMagenta)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} TRACE {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
customStderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} TRACE {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
proc logDebugStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgCyan)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} DEBUG {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
customStderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} DEBUG {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
proc logInfoStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgGreen)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} INFO {"-":>4} ({posix.getpid():03})] {message}""")
|
||||
customStderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} INFO {"-":>4} ({posix.getpid():03})] {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
proc logWarningStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgYellow)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} WARNING {"-":>1} ({posix.getpid():03})] {message}""")
|
||||
customStderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} WARNING {"-":>1} ({posix.getpid():03})] {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
proc logErrorStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgRed)
|
||||
stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} ERROR {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
customStderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} ERROR {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
|
||||
proc logCriticalStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgYellow)
|
||||
setBackgroundColor(bgRed)
|
||||
stderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<4} {"-":>1} CRITICAL {"-":>2} ({posix.getpid():03})]""")
|
||||
customStderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<4} {"-":>1} CRITICAL {"-":>2} ({posix.getpid():03})]""")
|
||||
setBackgroundColor(bgDefault)
|
||||
stderr.writeLine(&""" {message}""")
|
||||
customStderr.writeLine(&""" {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
|
||||
proc logFatalStderr(self: LogHandler, logger: Logger, message: string) =
|
||||
logger.lockFile(stderr)
|
||||
setForegroundColor(fgBlack)
|
||||
setBackgroundColor(bgRed)
|
||||
stderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<5} {"-":>1} {"":>1} FATAL {"-":>3} ({posix.getpid():03})]""")
|
||||
customStderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<5} {"-":>1} {"":>1} FATAL {"-":>3} ({posix.getpid():03})]""")
|
||||
setForegroundColor(fgRed)
|
||||
setBackgroundColor(bgDefault)
|
||||
stderr.writeline(&""" {message}""")
|
||||
customStderr.writeline(&""" {message}""")
|
||||
setForegroundColor(fgDefault)
|
||||
logger.unlockFile(stderr)
|
||||
|
||||
|
||||
proc logTraceFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} TRACE {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc logDebugFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} DEBUG {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc logInfoFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} INFO {"-":>4} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc logWarningFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} WARNING {"-":>1} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
proc logErrorFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<10} {"-":>1} {"":>1} ERROR {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc logCriticalFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<4} {"-":>1} CRITICAL {"-":>2} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc logFatalFile(self: LogHandler, logger: Logger, message: string) =
|
||||
var self = StreamHandler(self)
|
||||
logger.lockFile(self.file)
|
||||
self.file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss"):<5} {"-":>1} {"":>1} FATAL {"-":>3} ({posix.getpid():03})] {message}""")
|
||||
logger.unlockFile(self.file)
|
||||
|
||||
|
||||
|
||||
proc switchToFile*(self: Logger) =
|
||||
|
|
Loading…
Reference in New Issue