Implementation of :meth:`close`. This calls :meth:`~asyncio.Server.close` on the underlying :class:`asyncio.Server` object to stop accepting new connections and then closes open connections.
(
self,
close_connections: bool = True,
code: CloseCode | int = CloseCode.GOING_AWAY,
reason: str = "",
)
| 436 | ) |
| 437 | |
| 438 | async def _close( |
| 439 | self, |
| 440 | close_connections: bool = True, |
| 441 | code: CloseCode | int = CloseCode.GOING_AWAY, |
| 442 | reason: str = "", |
| 443 | ) -> None: |
| 444 | """ |
| 445 | Implementation of :meth:`close`. |
| 446 | |
| 447 | This calls :meth:`~asyncio.Server.close` on the underlying |
| 448 | :class:`asyncio.Server` object to stop accepting new connections and |
| 449 | then closes open connections. |
| 450 | |
| 451 | """ |
| 452 | self.logger.info("server closing") |
| 453 | |
| 454 | # Stop accepting new connections. |
| 455 | self.server.close() |
| 456 | |
| 457 | # Wait until all accepted connections reach connection_made() and call |
| 458 | # register(). See https://github.com/python/cpython/issues/79033 for |
| 459 | # details. This workaround can be removed when dropping Python < 3.11. |
| 460 | await asyncio.sleep(0) |
| 461 | |
| 462 | # After server.close(), handshake() closes OPENING connections with an |
| 463 | # HTTP 503 error. |
| 464 | |
| 465 | if close_connections: |
| 466 | # Close OPEN connections with code 1001 by default. |
| 467 | close_tasks = [ |
| 468 | asyncio.create_task(connection.close(code, reason)) |
| 469 | for connection in self.handlers |
| 470 | if connection.protocol.state is not CONNECTING |
| 471 | ] |
| 472 | # asyncio.wait doesn't accept an empty first argument. |
| 473 | if close_tasks: |
| 474 | await asyncio.wait(close_tasks) |
| 475 | |
| 476 | # Wait until all TCP connections are closed. |
| 477 | await self.server.wait_closed() |
| 478 | |
| 479 | # Wait until all connection handlers terminate. |
| 480 | # asyncio.wait doesn't accept an empty first argument. |
| 481 | if self.handlers: |
| 482 | await asyncio.wait(self.handlers.values()) |
| 483 | |
| 484 | # Tell wait_closed() to return. |
| 485 | self.closed_waiter.set_result(None) |
| 486 | |
| 487 | self.logger.info("server closed") |
| 488 | |
| 489 | async def wait_closed(self) -> None: |
| 490 | """ |
no test coverage detected