"feat: Implement Windows Socket documentation fix in multiple files"
This commit is contained in:
@@ -1 +1,201 @@
|
||||
|
||||
# Windows Socket-Fehler Fix Dokumentation
|
||||
|
||||
## Problem
|
||||
Bei der Entwicklung auf Windows-Systemen tritt ein Socket-Fehler beim Flask Auto-Reload auf:
|
||||
```
|
||||
OSError: [WinError 10038] Ein Vorgang bezog sich auf ein Objekt, das kein Socket ist
|
||||
```
|
||||
|
||||
## Ursache
|
||||
Das Problem entsteht durch:
|
||||
1. Flask's Auto-Reload-Feature startet den Server neu wenn Dateien geändert werden
|
||||
2. Der Queue Manager startet einen Daemon-Thread für Drucker-Überwachung
|
||||
3. Beim Neustart wird der alte Thread nicht ordnungsgemäß beendet
|
||||
4. Socket-Ressourcen werden nicht korrekt freigegeben
|
||||
5. Windows reagiert besonders empfindlich auf nicht geschlossene Sockets
|
||||
|
||||
## Lösung
|
||||
Implementierung eines mehrstufigen Fixes:
|
||||
|
||||
### 1. Verbesserter Queue Manager (`utils/queue_manager.py`)
|
||||
- **Threading.Event**: Verwendung von `threading.Event` statt `time.sleep()` für unterbrechbares Warten
|
||||
- **Non-Daemon Threads**: Threads werden als non-daemon erstellt für bessere Kontrolle
|
||||
- **Signal-Handler**: Windows-spezifische Signal-Handler für SIGINT, SIGTERM, SIGBREAK
|
||||
- **Thread-Locks**: Thread-sichere Operationen mit `threading.Lock()`
|
||||
- **Ordnungsgemäße Beendigung**: Timeout-basierte Thread-Beendigung mit Logging
|
||||
|
||||
```python
|
||||
# Verbessertes Shutdown-Handling
|
||||
def stop(self):
|
||||
with self._lock:
|
||||
if self.is_running:
|
||||
self.is_running = False
|
||||
self.shutdown_event.set()
|
||||
|
||||
if self.monitor_thread and self.monitor_thread.is_alive():
|
||||
self.monitor_thread.join(timeout=10)
|
||||
```
|
||||
|
||||
### 2. Windows-spezifische Fixes (`utils/windows_fixes.py`)
|
||||
- **Socket-Patches**: SO_REUSEADDR für Socket-Wiederverwendung
|
||||
- **Thread-Manager**: Zentrale Verwaltung aller Threads
|
||||
- **Signal-Handler**: SIGBREAK-Unterstützung für Windows
|
||||
- **Umgebungs-Optimierung**: UTF-8 Encoding und Thread-Pool-Einstellungen
|
||||
|
||||
```python
|
||||
def fix_windows_socket_issues():
|
||||
# Socket-Wiederverwendung aktivieren
|
||||
socket.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
```
|
||||
|
||||
### 3. Verbesserte App-Startup-Logik (`app.py`)
|
||||
- **Prozess-Erkennung**: Queue Manager nur im Hauptprozess starten
|
||||
- **Signal-Handling**: Windows-kompatible Signal-Handler
|
||||
- **Graceful Shutdown**: Koordinierte Beendigung aller Komponenten
|
||||
- **Auto-Reload-Erkennung**: Spezielle Behandlung für Flask Reloader
|
||||
|
||||
```python
|
||||
# Nur im Hauptprozess starten (nicht bei Flask Auto-Reload)
|
||||
if not debug_mode or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
|
||||
queue_manager = start_queue_manager()
|
||||
```
|
||||
|
||||
## Technische Details
|
||||
|
||||
### Threading-Verbesserungen
|
||||
```python
|
||||
# Alte Implementierung (problematisch)
|
||||
while self.is_running:
|
||||
self._check_waiting_jobs()
|
||||
time.sleep(self.check_interval) # Nicht unterbrechbar
|
||||
|
||||
# Neue Implementierung (robust)
|
||||
while self.is_running and not self.shutdown_event.is_set():
|
||||
self._check_waiting_jobs()
|
||||
if self.shutdown_event.wait(timeout=self.check_interval):
|
||||
break # Sofort beenden bei Shutdown-Signal
|
||||
```
|
||||
|
||||
### Signal-Handling
|
||||
```python
|
||||
# Windows-spezifische Signale
|
||||
if os.name == 'nt':
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
signal.signal(signal.SIGBREAK, signal_handler) # Windows-spezifisch
|
||||
```
|
||||
|
||||
### Socket-Optimierung
|
||||
```python
|
||||
# Gepatchte bind-Methode für Socket-Wiederverwendung
|
||||
def patched_bind(self, address):
|
||||
try:
|
||||
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
except:
|
||||
pass
|
||||
return self._bind_orig(address)
|
||||
```
|
||||
|
||||
## Vorteile der Lösung
|
||||
|
||||
### 1. Robustheit
|
||||
- Threads werden immer ordnungsgemäß beendet
|
||||
- Socket-Ressourcen werden korrekt freigegeben
|
||||
- Keine hängenden Prozesse bei Auto-Reload
|
||||
|
||||
### 2. Windows-Kompatibilität
|
||||
- Spezielle Behandlung für Windows-Eigenarten
|
||||
- SIGBREAK-Signal-Unterstützung
|
||||
- SO_REUSEADDR für Socket-Wiederverwendung
|
||||
|
||||
### 3. Entwicklerfreundlichkeit
|
||||
- Auto-Reload funktioniert ohne Fehler
|
||||
- Detailliertes Logging für Debugging
|
||||
- Automatische Cleanup-Prozesse
|
||||
|
||||
### 4. Produktions-Tauglichkeit
|
||||
- Graceful Shutdown in Produktionsumgebung
|
||||
- Thread-sichere Operationen
|
||||
- Robuste Fehlerbehandlung
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Environment-Variablen
|
||||
```bash
|
||||
# Für bessere Windows-Kompatibilität
|
||||
PYTHONIOENCODING=utf-8
|
||||
PYTHONUTF8=1
|
||||
WERKZEUG_RUN_MAIN=true
|
||||
```
|
||||
|
||||
### Flask-Konfiguration (Debug-Modus)
|
||||
```python
|
||||
if os.name == 'nt': # Windows
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=5000,
|
||||
debug=True,
|
||||
threaded=True,
|
||||
use_reloader=True,
|
||||
reloader_interval=1,
|
||||
passthrough_errors=False
|
||||
)
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Log-Ausgaben
|
||||
```
|
||||
✅ Printer Queue Manager erfolgreich gestartet
|
||||
🔄 Queue-Überwachung gestartet (Intervall: 120 Sekunden)
|
||||
🛑 Signal 2 empfangen - fahre System herunter...
|
||||
🔄 Beende Queue Manager...
|
||||
✅ Monitor-Thread erfolgreich beendet
|
||||
```
|
||||
|
||||
### Gesundheitsprüfung
|
||||
```python
|
||||
def is_healthy(self) -> bool:
|
||||
return (self.is_running and
|
||||
self.monitor_thread is not None and
|
||||
self.monitor_thread.is_alive() and
|
||||
not self.shutdown_event.is_set())
|
||||
```
|
||||
|
||||
## Bekannte Probleme und Workarounds
|
||||
|
||||
### Problem: Thread bleibt hängen
|
||||
**Lösung**: Timeout-basierte Thread-Beendigung mit Warnung
|
||||
|
||||
### Problem: Socket bereits in Verwendung
|
||||
**Lösung**: SO_REUSEADDR aktivieren
|
||||
|
||||
### Problem: Auto-Reload startet Queue Manager mehrfach
|
||||
**Lösung**: Prozess-Erkennung über WERKZEUG_RUN_MAIN
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Test mit Debug-Modus
|
||||
python app.py --debug
|
||||
|
||||
# Test mit Produktions-Modus
|
||||
python app.py
|
||||
|
||||
# Überwachung der Logs
|
||||
tail -f logs/app/app.log | grep "Queue Manager"
|
||||
```
|
||||
|
||||
## Wartung
|
||||
- Regelmäßige Überprüfung der Thread-Gesundheit
|
||||
- Monitoring der Socket-Verwendung
|
||||
- Log-Analyse für hanging Threads
|
||||
- Performance-Überwachung der Thread-Beendigung
|
||||
|
||||
## Fazit
|
||||
Dieser Fix behebt das Windows Socket-Problem vollständig durch:
|
||||
1. Ordnungsgemäße Thread-Verwaltung
|
||||
2. Windows-spezifische Socket-Behandlung
|
||||
3. Robuste Signal-Handler
|
||||
4. Graceful Shutdown-Mechanismen
|
||||
|
||||
Das System ist jetzt sowohl für Entwicklung als auch Produktion auf Windows-Systemen stabil einsetzbar.
|
Reference in New Issue
Block a user