Пример #1
0
    async def run_behaviors(self, behaviors: Tuple[BehaviorAPI, ...]) -> None:
        async with contextlib.AsyncExitStack() as stack:
            futures: List[asyncio.Task[Any]] = [
                create_task(self.manager.wait_finished(),
                            'Connection/run_behaviors/wait_finished')
            ]
            for behavior in behaviors:
                if behavior.should_apply_to(self):
                    behavior_exit = await stack.enter_async_context(
                        behavior.apply(self))
                    futures.append(behavior_exit)

            self.behaviors_applied.set()
            # If wait_first() is called, cleanup_tasks() will be a no-op, but if any post_apply()
            # calls raise an exception, it will ensure we don't leak pending tasks that would
            # cause asyncio to complain.
            async with cleanup_tasks(*futures):
                try:
                    for behavior in behaviors:
                        behavior.post_apply()
                    await wait_first(futures, max_wait_after_cancellation=2)
                except PeerConnectionLost:
                    # Any of our behaviors may propagate a PeerConnectionLost, which is to be
                    # expected as many Connection APIs used by them can raise that. To avoid a
                    # DaemonTaskExit since we're returning silently, ensure we're cancelled.
                    self.manager.cancel()
Пример #2
0
    async def _do_run(self) -> None:
        with child_process_logging(self._boot_info):
            endpoint_name = self.get_endpoint_name()
            event_bus_service = AsyncioEventBusService(
                self._boot_info.trinity_config,
                endpoint_name,
            )
            # FIXME: Must terminate component if event_bus_service terminates.
            async with background_asyncio_service(event_bus_service):
                event_bus = await event_bus_service.get_event_bus()
                loop_monitoring_task = create_task(
                    self._loop_monitoring_task(event_bus),
                    f'AsyncioIsolatedComponent/{self.name}/loop_monitoring_task'
                )

                # FIXME: Must terminate component if loop_monitoring_task terminates.
                async with cleanup_tasks(loop_monitoring_task):
                    try:
                        if self._boot_info.profile:
                            with profiler(
                                    f'profile_{self.get_endpoint_name()}'):
                                await self.do_run(event_bus)
                        else:
                            # XXX: When open_in_process() injects a KeyboardInterrupt into us (via
                            # coro.throw()), we hang forever here, until open_in_process() times
                            # out and sends us a SIGTERM, at which point we exit without executing
                            # either the except or the finally blocks below.
                            # See https://github.com/ethereum/trinity/issues/1711 for more.
                            await self.do_run(event_bus)
                    except KeyboardInterrupt:
                        # Currently we never reach this code path, but when we fix the issue above
                        # it will be needed.
                        return
                    finally:
                        # Once we start seeing this in the logs after a Ctrl-C, we'll likely have
                        # figured out the issue above.
                        self.logger.debug("%s: do_run() finished", self)