Start the server
(self)
| 155 | logger.info("Server shutting down gracefully...") |
| 156 | |
| 157 | async def start(self): |
| 158 | """Start the server""" |
| 159 | # Check if port is already in use |
| 160 | import socket |
| 161 | port = self.config['port'] |
| 162 | host = self.config['server']['host'] |
| 163 | |
| 164 | # Try to bind to the port to check if it's available |
| 165 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 166 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 167 | try: |
| 168 | # Try to bind to the port |
| 169 | if host == '0.0.0.0': |
| 170 | # Check on localhost since 0.0.0.0 means all interfaces |
| 171 | sock.bind(('127.0.0.1', port)) |
| 172 | else: |
| 173 | sock.bind((host, port)) |
| 174 | except OSError as e: |
| 175 | sock.close() # Make sure to close the socket on error |
| 176 | if e.errno == 48: # Address already in use on macOS |
| 177 | logger.error(f"Port {port} is already in use!") |
| 178 | logger.error("Another server instance may be running.") |
| 179 | logger.error(f"To find the process: lsof -i :{port}") |
| 180 | logger.error(f"To kill it: kill $(lsof -t -i :{port})") |
| 181 | raise SystemExit(f"Error: Port {port} is already in use. Please stop the other server or use a different port.") from e |
| 182 | elif e.errno == 98: # Address already in use on Linux |
| 183 | logger.error(f"Port {port} is already in use!") |
| 184 | logger.error("Another server instance may be running.") |
| 185 | logger.error(f"To find the process: netstat -tulpn | grep {port}") |
| 186 | raise SystemExit(f"Error: Port {port} is already in use. Please stop the other server or use a different port.") from e |
| 187 | else: |
| 188 | # Re-raise other socket errors |
| 189 | raise |
| 190 | finally: |
| 191 | # Always close the socket |
| 192 | sock.close() |
| 193 | |
| 194 | self.app = await self.create_app() |
| 195 | |
| 196 | # Create runner |
| 197 | self.runner = web.AppRunner( |
| 198 | self.app, |
| 199 | keepalive_timeout=75, # Match aiohttp default |
| 200 | access_log_format='%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"' |
| 201 | ) |
| 202 | |
| 203 | await self.runner.setup() |
| 204 | |
| 205 | # Check platform support for reuse_port |
| 206 | reuse_port_supported = sys.platform not in ['win32', 'cygwin'] |
| 207 | |
| 208 | # Setup SSL |
| 209 | ssl_context = self._setup_ssl_context() |
| 210 | |
| 211 | # Create site |
| 212 | self.site = web.TCPSite( |
| 213 | self.runner, |
| 214 | self.config['server']['host'], |
no test coverage detected