jw-python/tools/python/jwutils/Process.py
Jan Lindemann 77d43aebad Add type annotations from monkeytype + jw-devops/test
Add type annotations as generated by monkeytype and jw-devops/test, plus some
hand editing to satisfy both monkeytype and mypy.

Signed-off-by: Jan Lindemann <jan@janware.com>
2020-04-10 17:55:36 +02:00

70 lines
1.9 KiB
Python

from __future__ import annotations
from abc import ABC, abstractmethod
from enum import Enum, Flag, auto
from typing import List
def _sigchld_handler(signum, process):
if not signum == signal.SIGCHLD:
return
Process.propagate_signal(signum)
class Process(ABC): # export
__processes: List[Process] = []
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