mirror of https://github.com/nocturn9x/nimd.git
Failed attempts to fix missing stderr from supervised processes
This commit is contained in:
parent
d6c46b3543
commit
b68b6f5e74
|
@ -23,10 +23,10 @@ import shutdown
|
|||
|
||||
|
||||
|
||||
proc mainLoop*(logger: Logger) =
|
||||
proc mainLoop*(logger: Logger, workers: int = 1) =
|
||||
## NimD's main execution loop
|
||||
logger.info("Processing default runlevel")
|
||||
startServices(logger, workers=1, level=Default)
|
||||
startServices(logger, workers=workers, level=Default)
|
||||
logger.debug(&"Unblocking signals")
|
||||
unblockSignals(logger)
|
||||
logger.info("System initialization complete, idling on control socket")
|
||||
|
|
|
@ -219,14 +219,13 @@ proc removeService*(service: Service) =
|
|||
break
|
||||
|
||||
|
||||
proc loggerWorker(logger: Logger, service: Service, process: Process) =
|
||||
proc streamLoggerWorker(logger: Logger, service: Service, stream: Stream) =
|
||||
## Captures the output of a given process and relays it
|
||||
## in a formatted manner into our logging system
|
||||
try:
|
||||
logger.debug("Switching logs to file")
|
||||
logger.switchToFile()
|
||||
# logger.switchToFile()
|
||||
var line: string = ""
|
||||
var stream = process.outputStream
|
||||
while stream.readLine(line):
|
||||
logger.info(&"{service.name}: {line}")
|
||||
except:
|
||||
|
@ -244,63 +243,62 @@ proc supervisorWorker(logger: Logger, service: Service, process: Process) =
|
|||
logger.error(&"Error, cannot fork: {posix.strerror(posix.errno)}")
|
||||
elif p == 0:
|
||||
logger.trace(&"New child has been spawned")
|
||||
loggerWorker(logger, service, process)
|
||||
else:
|
||||
var pid = process.processID
|
||||
var status: cint
|
||||
var returnCode: int
|
||||
var sig: int
|
||||
var process: Process
|
||||
logger.debug("Switching logs to file")
|
||||
logger.switchToFile()
|
||||
while true:
|
||||
logger.trace(&"Calling waitpid() on {pid}")
|
||||
returnCode = posix.waitPid(cint(pid), status, WUNTRACED)
|
||||
if WIFEXITED(status):
|
||||
sig = 0
|
||||
elif WIFSIGNALED(status):
|
||||
sig = WTERMSIG(status)
|
||||
else:
|
||||
sig = -1
|
||||
logger.trace(&"Call to waitpid() set status to {status} and returned {returnCode}, setting sig to {sig}")
|
||||
case service.restart:
|
||||
of Never:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has exited, shutting down controlling process")
|
||||
streamLoggerWorker(logger, service, process.outputStream)
|
||||
var pid = process.processID
|
||||
var status: cint
|
||||
var returnCode: int
|
||||
var sig: int
|
||||
var process: Process
|
||||
logger.debug("Switching logs to file")
|
||||
logger.switchToFile()
|
||||
while true:
|
||||
logger.trace(&"Calling waitpid() on {pid}")
|
||||
returnCode = posix.waitPid(cint(pid), status, WUNTRACED)
|
||||
if WIFEXITED(status):
|
||||
sig = 0
|
||||
elif WIFSIGNALED(status):
|
||||
sig = WTERMSIG(status)
|
||||
else:
|
||||
sig = -1
|
||||
logger.trace(&"Call to waitpid() set status to {status} and returned {returnCode}, setting sig to {sig}")
|
||||
case service.restart:
|
||||
of Never:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has exited, shutting down controlling process")
|
||||
break
|
||||
of Always:
|
||||
if sig > 0:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||
elif sig == 0:
|
||||
logger.info(&"Service '{service.name}' has exited gracefully, sleeping {service.restartDelay} seconds before restarting it")
|
||||
else:
|
||||
logger.info(&"Service '{service.name}' has exited, sleeping {service.restartDelay} seconds before restarting it")
|
||||
removeManagedProcess(pid)
|
||||
sleep(service.restartDelay * 1000)
|
||||
var split = shlex(service.exec)
|
||||
if split.error:
|
||||
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||
break
|
||||
of Always:
|
||||
if sig > 0:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||
elif sig == 0:
|
||||
logger.info(&"Service '{service.name}' has exited gracefully, sleeping {service.restartDelay} seconds before restarting it")
|
||||
else:
|
||||
logger.info(&"Service '{service.name}' has exited, sleeping {service.restartDelay} seconds before restarting it")
|
||||
removeManagedProcess(pid)
|
||||
sleep(service.restartDelay * 1000)
|
||||
var split = shlex(service.exec)
|
||||
if split.error:
|
||||
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||
break
|
||||
var arguments = split.words
|
||||
let progName = arguments[0]
|
||||
arguments = arguments[1..^1]
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||
pid = process.processID()
|
||||
of OnFailure:
|
||||
if sig > 0:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||
removeManagedProcess(pid)
|
||||
sleep(service.restartDelay * 1000)
|
||||
var split = shlex(service.exec)
|
||||
if split.error:
|
||||
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||
break
|
||||
var arguments = split.words
|
||||
let progName = arguments[0]
|
||||
arguments = arguments[1..^1]
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||
pid = process.processID()
|
||||
if process != nil:
|
||||
process.close()
|
||||
var arguments = split.words
|
||||
let progName = arguments[0]
|
||||
arguments = arguments[1..^1]
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||
pid = process.processID()
|
||||
of OnFailure:
|
||||
if sig > 0:
|
||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||
removeManagedProcess(pid)
|
||||
sleep(service.restartDelay * 1000)
|
||||
var split = shlex(service.exec)
|
||||
if split.error:
|
||||
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||
break
|
||||
var arguments = split.words
|
||||
let progName = arguments[0]
|
||||
arguments = arguments[1..^1]
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||
pid = process.processID()
|
||||
if process != nil:
|
||||
process.close()
|
||||
|
||||
|
||||
proc startService(logger: Logger, service: Service) =
|
||||
|
@ -319,7 +317,7 @@ proc startService(logger: Logger, service: Service) =
|
|||
var arguments = split.words
|
||||
let progName = arguments[0]
|
||||
arguments = arguments[1..^1]
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments, options=if service.useParentStreams: {poParentStreams} else: {poUsePath, poDaemon, poStdErrToStdOut})
|
||||
process = startProcess(progName, workingDir=service.workDir, args=arguments, options=if service.useParentStreams: {poParentStreams, poStdErrToStdOut} else: {poUsePath, poDaemon, poStdErrToStdOut})
|
||||
if service.supervised or service.kind != Oneshot:
|
||||
var pid = posix.fork()
|
||||
if pid == -1:
|
||||
|
@ -329,7 +327,7 @@ proc startService(logger: Logger, service: Service) =
|
|||
supervisorWorker(logger, service, process)
|
||||
# If the service is unsupervised we just spawn the logger worker (assuming it doesn't use poParentStreams)
|
||||
if not service.useParentStreams:
|
||||
loggerWorker(logger, service, process)
|
||||
streamLoggerWorker(logger, service, process.outputStream)
|
||||
except:
|
||||
logger.error(&"Error while starting service '{service.name}': {getCurrentExceptionMsg()}")
|
||||
|
||||
|
|
27
src/main.nim
27
src/main.nim
|
@ -44,30 +44,25 @@ proc addStuff =
|
|||
addShutdownHandler(newShutdownHandler(unmountAllDisks))
|
||||
# Adds test services
|
||||
var echoer = newService(name="echoer", description="prints owo", exec="/bin/echo owoooooooooo",
|
||||
runlevel=Boot, kind=Oneshot, workDir=getCurrentDir(),
|
||||
supervised=false, restart=Never, restartDelay=0,
|
||||
runlevel=Boot, kind=Simple, workDir=getCurrentDir(),
|
||||
supervised=false, restart=Always, restartDelay=5,
|
||||
depends=(@[]), provides=(@[]))
|
||||
var errorer = newService(name="errorer", description="la mamma di gavd",
|
||||
exec="/bin/false", supervised=true, restart=OnFailure,
|
||||
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple,
|
||||
depends=(@[newDependency(Other, echoer)]), provides=(@[]))
|
||||
var test = newService(name="broken", description="", exec="/bin/echo owo",
|
||||
runlevel=Boot, kind=Oneshot, workDir=getCurrentDir(),
|
||||
supervised=false, restart=Never, restartDelay=0,
|
||||
depends=(@[newDependency(Other, echoer)]), provides=(@[]))
|
||||
exec="/bin/false", supervised=true, restart=OnFailure,
|
||||
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple,
|
||||
depends=(@[]), provides=(@[]))
|
||||
var exiter = newService(name="exiter", description="la mamma di licenziat",
|
||||
exec="/bin/true", supervised=true, restart=Always,
|
||||
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple,
|
||||
depends=(@[newDependency(Other, errorer)]), provides=(@[]))
|
||||
exec="/bin/true", supervised=true, restart=Always,
|
||||
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple,
|
||||
depends=(@[newDependency(Other, errorer)]), provides=(@[]))
|
||||
var shell = newService(name="login", description="A simple login shell", kind=Simple,
|
||||
getCurrentDir(), runlevel=Boot, exec="/bin/login -f root",
|
||||
supervised=true, restart=Always, restartDelay=0, depends=(@[]), provides=(@[]),
|
||||
getCurrentDir(), runlevel=Default, exec="/bin/login -f root",
|
||||
supervised=true, restart=Always, restartDelay=5, depends=(@[]), provides=(@[]),
|
||||
useParentStreams=true
|
||||
)
|
||||
addService(errorer)
|
||||
addService(echoer)
|
||||
addService(exiter)
|
||||
addService(test)
|
||||
addService(shell)
|
||||
|
||||
|
||||
|
@ -126,7 +121,7 @@ proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab",
|
|||
logger.info("Processing boot runlevel")
|
||||
startServices(logger, workers=workerCount, level=Boot)
|
||||
logger.debug("Starting main loop")
|
||||
mainLoop(logger)
|
||||
mainLoop(logger, workers=workerCount)
|
||||
|
||||
|
||||
when isMainModule:
|
||||
|
|
Loading…
Reference in New Issue