Projektarbeit-MYP/backend/docs/WINDOWS_SOCKET_FIX_DOCUMENTATION.md
2025-05-31 22:40:29 +02:00

5.9 KiB

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
# 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
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
# 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

# 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

# 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

# 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

# Für bessere Windows-Kompatibilität
PYTHONIOENCODING=utf-8
PYTHONUTF8=1
WERKZEUG_RUN_MAIN=true

Flask-Konfiguration (Debug-Modus)

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

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

# 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.