Binds sockets, starts workers, and begins proxying messages.
(self)
| 684 | return False |
| 685 | |
| 686 | def start(self) -> None: |
| 687 | """Binds sockets, starts workers, and begins proxying messages.""" |
| 688 | if self._client_socket is None: |
| 689 | raise RuntimeError( |
| 690 | "Server must be bound to an address before starting. Call bind() first." |
| 691 | ) |
| 692 | |
| 693 | self._client_socket.setup_lazily() |
| 694 | logger.info(f"RPC Server started and listening on {self._address}") |
| 695 | |
| 696 | # Create and configure the event loop |
| 697 | self._loop = asyncio.new_event_loop() |
| 698 | |
| 699 | self._shutdown_event = asyncio.Event() |
| 700 | |
| 701 | async def run_server(): |
| 702 | """Run the server until shutdown.""" |
| 703 | try: |
| 704 | await self._run_server() |
| 705 | except asyncio.CancelledError: |
| 706 | logger_debug("[server] Server task cancelled") |
| 707 | except Exception as e: |
| 708 | logger.error(f"Server error: {e}") |
| 709 | logger.error(traceback.format_exc()) |
| 710 | finally: |
| 711 | # Cancel all worker tasks |
| 712 | for task in self._worker_tasks: |
| 713 | if not task.done(): |
| 714 | task.cancel() |
| 715 | # Wait for all tasks to complete |
| 716 | if self._worker_tasks: |
| 717 | await asyncio.gather(*self._worker_tasks, |
| 718 | return_exceptions=True) |
| 719 | |
| 720 | # Drain any remaining requests and send cancellation responses |
| 721 | await self._drain_pending_requests() |
| 722 | |
| 723 | logger_debug("[server] All server tasks completed") |
| 724 | |
| 725 | self._main_task = self._loop.create_task(run_server()) |
| 726 | |
| 727 | def run_loop(): |
| 728 | asyncio.set_event_loop(self._loop) |
| 729 | try: |
| 730 | self._loop.run_until_complete(self._main_task) |
| 731 | except RuntimeError as e: |
| 732 | # This can happen if the event loop is stopped while futures are pending |
| 733 | error_str = str(e) |
| 734 | if "Event loop stopped before Future completed" in error_str: |
| 735 | # This is expected during shutdown - ignore it |
| 736 | logger.debug( |
| 737 | f"[server] Expected shutdown error: {error_str}") |
| 738 | else: |
| 739 | # This is an unexpected RuntimeError - log full details |
| 740 | import traceback |
| 741 | logger.error(f"Event loop error: {error_str}") |
| 742 | logger.error(f"Traceback: {traceback.format_exc()}") |
| 743 | except Exception as e: |