3.6 KiB
3.6 KiB
Update Feature Fixes - Final Summary
Problem Identified
The update feature was causing the application to hang indefinitely when clicked. The issue had two components:
- UI Thread Blocking: The original code was running download operations synchronously on the UI thread
- Network Timeout Issues: Even with timeouts set, the socket-level network calls would hang indefinitely if the server didn't respond
Solutions Implemented
1. Background Threading (First Fix)
- Created
UpdateDownloadWorkerclass to run download operations in a background thread - Moved blocking network calls off the UI thread
- This prevents the UI from freezing while waiting for network operations
2. Aggressive Timeout Strategy (Second Fix)
Applied timeouts at multiple levels to ensure the app never hangs:
A. Socket-Level Timeout (Most Important)
- File:
src/webdrop_bridge/core/updater.py - Reduced
urlopen()timeout from 10 seconds to 5 seconds - This is the first line of defense against hanging socket connections
- Applied in
_fetch_release()method
B. Asyncio-Level Timeout
- File:
src/webdrop_bridge/ui/main_window.pyandsrc/webdrop_bridge/core/updater.py UpdateCheckWorker: 10-second timeout on entire check operationUpdateDownloadWorker: 300-second timeout on download, 30-second on verificationcheck_for_updates(): 8-second timeout on async executor- These catch any remaining hangs in the asyncio operations
C. Qt-Level Timeout (Final Safety Net)
- File:
src/webdrop_bridge/ui/main_window.py - Update check: 30-second QTimer safety timeout (
_run_async_check()) - Download: 10-minute QTimer safety timeout (
_perform_update_async()) - If nothing else works, Qt's event loop will forcefully close the operation
3. Error Handling Improvements
- Added proper exception handling for
asyncio.TimeoutError - Better logging to identify where hangs occur
- User-friendly error messages like "no server response" or "Operation timed out"
- Graceful degradation: operations fail fast instead of hanging
Timeout Hierarchy (in seconds)
Update Check Flow:
QTimer safety net: 30s ─┐
├─ Asyncio timeout: 10s ─┐
├─ Socket timeout: 5s (first to trigger)
Download Flow:
QTimer safety net: 600s ─┐
├─ Asyncio timeout: 300s ─┐
├─ Socket timeout: 5s (first to trigger)
Files Modified
-
src/webdrop_bridge/ui/main_window.py
- Updated
UpdateCheckWorker.run()with timeout handling - Updated
UpdateDownloadWorker.run()with timeout handling - Added QTimer safety timeouts in
_run_async_check()and_perform_update_async() - Proper event loop cleanup in finally blocks
- Updated
-
src/webdrop_bridge/core/updater.py
- Reduced socket timeout in
_fetch_release()from 10s to 5s - Added timeout to
check_for_updates()async operation - Added timeout to
download_update()async operation - Added timeout to
verify_checksum()async operation - Better error logging with exception types
- Reduced socket timeout in
Testing
- All 7 integration tests pass
- Timeout verification script confirms all timeout mechanisms are in place
- No syntax errors in modified code
Result
The application will no longer hang indefinitely when checking for or downloading updates. Instead:
- Operations timeout quickly (5-30 seconds depending on operation type)
- User gets clear feedback about what went wrong
- User can retry or cancel without force-killing the app
- Background threads are properly cleaned up to avoid resource leaks