Add web server error handling and proper shutdown

- Add stop() method to WebServer class
- Store server instance for graceful shutdown
- Add error handling in start_server() with user-friendly alert
- Show warning dialog if server fails to start (e.g., port in use)
- Stop server in closeEvent before application exit
- Add status bar messages for server state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-03 17:15:38 -08:00
parent 418407b2b9
commit f6743339c0
2 changed files with 49 additions and 5 deletions

View File

@@ -330,14 +330,48 @@ class MainWindow(QMainWindow):
def start_server(self): def start_server(self):
"""Start the web server in a background thread.""" """Start the web server in a background thread."""
self.web_server.create_app() self.server_error = None
def run(): def run():
self.web_server.run() try:
self.web_server.create_app()
self.web_server.run()
except Exception as e:
self.server_error = str(e)
# Emit signal to show error on main thread
QTimer.singleShot(0, self.show_server_error)
self.server_thread = threading.Thread(target=run, daemon=True) self.server_thread = threading.Thread(target=run, daemon=True)
self.server_thread.start() self.server_thread.start()
self.status_bar.showMessage(f"Server running on port {DEFAULT_PORT}")
# Give the server a moment to start, then check for errors
QTimer.singleShot(1000, self.check_server_started)
def check_server_started(self):
"""Check if server started successfully."""
if self.server_error:
self.show_server_error()
else:
self.status_bar.showMessage(f"Server running on port {DEFAULT_PORT}")
def show_server_error(self):
"""Show server error dialog."""
error_msg = self.server_error or "Unknown error"
self.status_bar.showMessage(f"Server failed to start")
QMessageBox.warning(
self,
"Web Server Error",
f"Failed to start web server on port {DEFAULT_PORT}.\n\n"
f"Error: {error_msg}\n\n"
"The web interface will not be available.\n"
"Check if another application is using the port."
)
def stop_server(self):
"""Stop the web server."""
if self.web_server:
self.web_server.stop()
self.status_bar.showMessage("Server stopped")
def update_ip_label(self): def update_ip_label(self):
"""Update the IP address label.""" """Update the IP address label."""
@@ -510,7 +544,12 @@ class MainWindow(QMainWindow):
def closeEvent(self, event): def closeEvent(self, event):
"""Handle window close.""" """Handle window close."""
# Stop the web server
self.stop_server()
# Hide tray icon
self.tray_icon.hide() self.tray_icon.hide()
event.accept() event.accept()
def resizeEvent(self, event): def resizeEvent(self, event):

View File

@@ -254,8 +254,13 @@ class WebServer:
port=self.port, port=self.port,
log_level="warning" log_level="warning"
) )
server = uvicorn.Server(config) self.server = uvicorn.Server(config)
server.run() self.server.run()
def stop(self):
"""Stop the web server."""
if self.server:
self.server.should_exit = True
async def run_async(self): async def run_async(self):
"""Run the web server asynchronously.""" """Run the web server asynchronously."""