Add Process and Signals support

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2019-10-29 11:25:03 +01:00
commit c96ffe52c0
6 changed files with 139 additions and 0 deletions

View file

@ -0,0 +1,68 @@
from abc import ABC, abstractmethod
from enum import Enum, Flag, auto
def _sigchld_handler(signum, process):
if not signum == signal.SIGCHLD:
return
Process.propagate_signal(signum)
class Process(ABC): # export
__processes = []
class State(Enum):
Running = auto()
Shutdown = auto()
Done = auto()
class Flags(Flag):
FailOnExitWithoutShutdown = auto()
def __init__(self):
self.__state = Running
self.__flags = Flags.FailOnExitWithoutShutdown
if len(self.__processes) == 0:
self._signals().add_handler(signals.SIGCHLD, _sigchld_handler)
self.__processes.add(self)
@classmethod
def propagate_signal(cls, signum):
for p in cls.__processes:
p.__signal(signum)
def signal(self, signum):
if signum == signals.SIGCHLD:
self.exited()
@abstractmethod
def _pid(self):
pass
@classmethod
@abstractmethod
def signals(cls):
pass
# to be reimplemented
def _request_shutdown(self):
pass
# to be reimplemented
def name(self):
return str(self._pid())
def request_shutdown(self):
if not self.__state == Shutdown:
self.__state = Shutdown
self._request_shutdown()
def exited(self):
if self.__state == Process.State.Running:
slog(ERR, 'process "{}" exited unexpectedly'.format(process.name()))
if __flags & Process.Flags.FailOnExitWithoutShutdown:
slog(ERR, 'exiting')
exit(1)
self.__state = Process.State.Done
self.__processes.erase(self)
if len(self.__processes) == 0:
self._signals().remove_handler(signals.SIGCHLD) # FIXME: broken logic