(self, sockets: list[socket.socket] | None = None)
| 102 | logger.info(message, process_id, extra={"color_message": color_message}) |
| 103 | |
| 104 | async def startup(self, sockets: list[socket.socket] | None = None) -> None: |
| 105 | await self.lifespan.startup() |
| 106 | if self.lifespan.should_exit: |
| 107 | self.should_exit = True |
| 108 | return |
| 109 | |
| 110 | config = self.config |
| 111 | |
| 112 | def create_protocol( |
| 113 | _loop: asyncio.AbstractEventLoop | None = None, |
| 114 | ) -> asyncio.Protocol: |
| 115 | return config.http_protocol_class( # type: ignore[call-arg] |
| 116 | config=config, |
| 117 | server_state=self.server_state, |
| 118 | app_state=self.lifespan.state, |
| 119 | _loop=_loop, |
| 120 | ) |
| 121 | |
| 122 | loop = asyncio.get_running_loop() |
| 123 | |
| 124 | listeners: Sequence[socket.SocketType] |
| 125 | if sockets is not None: # pragma: full coverage |
| 126 | # Explicitly passed a list of open sockets. |
| 127 | # We use this when the server is run from a Gunicorn worker. |
| 128 | |
| 129 | def _share_socket( |
| 130 | sock: socket.SocketType, |
| 131 | ) -> socket.SocketType: # pragma py-not-win32 |
| 132 | # Windows requires the socket be explicitly shared across |
| 133 | # multiple workers (processes). |
| 134 | from socket import fromshare # type: ignore[attr-defined] |
| 135 | |
| 136 | sock_data = sock.share(os.getpid()) # type: ignore[attr-defined] |
| 137 | return fromshare(sock_data) |
| 138 | |
| 139 | self.servers: list[asyncio.base_events.Server] = [] |
| 140 | for sock in sockets: |
| 141 | is_windows = platform.system() == "Windows" |
| 142 | if config.workers > 1 and is_windows: # pragma: py-not-win32 |
| 143 | sock = _share_socket(sock) # type: ignore[assignment] |
| 144 | server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog) |
| 145 | self.servers.append(server) |
| 146 | listeners = sockets |
| 147 | |
| 148 | elif config.fd is not None: # pragma: py-win32 |
| 149 | # Use an existing socket, from a file descriptor. |
| 150 | sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM) |
| 151 | server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog) |
| 152 | assert server.sockets is not None # mypy |
| 153 | listeners = server.sockets |
| 154 | self.servers = [server] |
| 155 | |
| 156 | elif config.uds is not None: # pragma: py-win32 |
| 157 | # Create a socket using UNIX domain socket. |
| 158 | uds_perms = 0o666 |
| 159 | if os.path.exists(config.uds): |
| 160 | uds_perms = os.stat(config.uds).st_mode # pragma: full coverage |
| 161 | server = await loop.create_unix_server( |
no test coverage detected