예제 #1
0
    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
예제 #2
0
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))