async def __handle_crash_sub_services(self, process: ModuleProcess): try: self.__sub_processes.remove(process) process.join() logging.critical(f"Channel sub process crash occurred. process={process}") async def _close(): if not self.__loop_for_sub_services.is_closed(): self._channel_service.close() asyncio.ensure_future(_close(), loop=self.__loop_for_sub_services) except ValueError: # Call this function by cleanup pass
class _BroadcastSchedulerMp(BroadcastScheduler): def __init__(self, channel: str, self_target: str = None): super().__init__() self.__channel = channel self.__self_target = self_target self.__process = ModuleProcess() self.__broadcast_queue = self.__process.Queue() self.__broadcast_queue.cancel_join_thread() @staticmethod def _main(broadcast_queue: mp.Queue, channel: str, self_target: str, properties: ModuleProcessProperties = None): if properties is not None: ModuleProcess.load_properties(properties, f"{channel}_broadcast") logging.info(f"BroadcastScheduler process({channel}) start") broadcast_queue.cancel_join_thread() broadcaster = _Broadcaster(channel, self_target) broadcaster.start() original_sigterm_handler = signal.getsignal(signal.SIGTERM) original_sigint_handler = signal.getsignal(signal.SIGINT) def _signal_handler(signal_num, frame): signal.signal(signal.SIGTERM, original_sigterm_handler) signal.signal(signal.SIGINT, original_sigint_handler) logging.error( f"BroadcastScheduler process({channel}) has been received signal({signal_num})" ) broadcast_queue.put((None, None)) broadcaster.stop() signal.signal(signal.SIGTERM, _signal_handler) signal.signal(signal.SIGINT, _signal_handler) while True: command, params = broadcast_queue.get() if not broadcaster.is_running or command is None: break broadcaster.handle_command(command, params) while not broadcast_queue.empty(): broadcast_queue.get() logging.info(f"BroadcastScheduler process({channel}) end") def start(self): def crash_callback_in_join_thread(process: ModuleProcess): os.kill(os.getpid(), signal.SIGTERM) args = (self.__broadcast_queue, self.__channel, self.__self_target) self.__process.start( target=_BroadcastSchedulerMp._main, args=args, crash_callback_in_join_thread=crash_callback_in_join_thread) def stop(self): logging.info(f"Terminate BroadcastScheduler process({self})") self.__process.terminate() def wait(self): self.__process.join() def _put_command(self, command, params, block=False, block_timeout=None): self.__broadcast_queue.put((command, params))