"feat: Enhanced Windows compatibility in backend utilities"

This commit is contained in:
2025-05-29 13:03:28 +02:00
parent 1307614243
commit 1297f3af3c
2 changed files with 46 additions and 19 deletions

View File

@@ -19,14 +19,17 @@ import subprocess
import json import json
import signal import signal
# Windows-spezifische Fixes früh importieren # Windows-spezifische Fixes früh importieren (nur einmal)
if os.name == 'nt': if os.name == 'nt':
try: try:
from utils.windows_fixes import get_windows_thread_manager, apply_all_windows_fixes from utils.windows_fixes import get_windows_thread_manager
apply_all_windows_fixes() # apply_all_windows_fixes() wird automatisch beim Import ausgeführt
except ImportError: except ImportError as e:
# Fallback falls windows_fixes nicht verfügbar # Fallback falls windows_fixes nicht verfügbar
get_windows_thread_manager = None get_windows_thread_manager = None
print(f"⚠️ Windows-Fixes nicht verfügbar: {str(e)}")
else:
get_windows_thread_manager = None
# Lokale Imports # Lokale Imports
from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification

View File

@@ -15,6 +15,10 @@ from utils.logging_config import get_logger
# Logger für Windows-Fixes # Logger für Windows-Fixes
windows_logger = get_logger("windows_fixes") windows_logger = get_logger("windows_fixes")
# Globale Flags um doppelte Anwendung zu verhindern
_windows_fixes_applied = False
_socket_patches_applied = False
class WindowsThreadManager: class WindowsThreadManager:
""" """
Verwaltet Threads und deren ordnungsgemäße Beendigung auf Windows. Verwaltet Threads und deren ordnungsgemäße Beendigung auf Windows.
@@ -118,24 +122,42 @@ def fix_windows_socket_issues():
Anwendung von Windows-spezifischen Socket-Fixes. Anwendung von Windows-spezifischen Socket-Fixes.
Verhindert Socket-Fehler beim Flask Auto-Reload. Verhindert Socket-Fehler beim Flask Auto-Reload.
""" """
global _socket_patches_applied
if os.name != 'nt': if os.name != 'nt':
return return
if _socket_patches_applied:
windows_logger.debug("⏭️ Socket-Patches bereits angewendet")
return
try: try:
# Socket-Wiederverwendung aktivieren # Socket-Wiederverwendung aktivieren durch monkey-patching
import socket import socket
socket.socket._bind_orig = socket.socket.bind
# Speichere die ursprüngliche bind-Methode nur einmal
if not hasattr(socket.socket, '_original_bind'):
socket.socket._original_bind = socket.socket.bind
def patched_bind(self, address): def patched_bind(self, address):
"""Gepatchte bind-Methode mit SO_REUSEADDR.""" """Gepatchte bind-Methode mit SO_REUSEADDR."""
try: try:
# SO_REUSEADDR setzen
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except: except Exception as e:
pass # Ignoriere Fehler, aber logge sie für Debug-Zwecke
return self._bind_orig(address) windows_logger.debug(f"SO_REUSEADDR konnte nicht gesetzt werden: {str(e)}")
socket.socket.bind = patched_bind # Rufe die ursprüngliche bind-Methode auf
windows_logger.debug("✅ Windows Socket-Patches angewendet") return socket.socket._original_bind(self, address)
# Patch nur anwenden wenn noch nicht geschehen
if socket.socket.bind.__name__ != 'patched_bind':
socket.socket.bind = patched_bind
_socket_patches_applied = True
windows_logger.debug("✅ Windows Socket-Patches angewendet")
else:
windows_logger.debug("⏭️ Socket bereits gepatcht")
except Exception as e: except Exception as e:
windows_logger.warning(f"⚠️ Socket-Patches konnten nicht angewendet werden: {str(e)}") windows_logger.warning(f"⚠️ Socket-Patches konnten nicht angewendet werden: {str(e)}")
@@ -152,11 +174,6 @@ def setup_windows_environment():
os.environ['PYTHONIOENCODING'] = 'utf-8' os.environ['PYTHONIOENCODING'] = 'utf-8'
os.environ['PYTHONUTF8'] = '1' os.environ['PYTHONUTF8'] = '1'
# Thread-Pool-Größe optimieren
if 'WERKZEUG_SERVER_FD' not in os.environ:
# Nur im Hauptprozess
os.environ['WERKZEUG_RUN_MAIN'] = 'true'
windows_logger.debug("✅ Windows-Umgebung optimiert") windows_logger.debug("✅ Windows-Umgebung optimiert")
except Exception as e: except Exception as e:
@@ -172,10 +189,16 @@ def apply_all_windows_fixes():
""" """
Wendet alle Windows-spezifischen Fixes an. Wendet alle Windows-spezifischen Fixes an.
""" """
global _windows_fixes_applied
if os.name != 'nt': if os.name != 'nt':
windows_logger.debug("⏭️ Keine Windows-Fixes nötig (nicht Windows)") windows_logger.debug("⏭️ Keine Windows-Fixes nötig (nicht Windows)")
return return
if _windows_fixes_applied:
windows_logger.debug("⏭️ Windows-Fixes bereits angewendet")
return
windows_logger.info("🔧 Wende Windows-spezifische Fixes an...") windows_logger.info("🔧 Wende Windows-spezifische Fixes an...")
setup_windows_environment() setup_windows_environment()
@@ -184,11 +207,12 @@ def apply_all_windows_fixes():
# Thread-Manager initialisieren # Thread-Manager initialisieren
thread_manager = get_windows_thread_manager() thread_manager = get_windows_thread_manager()
# Atexit-Handler registrieren # Atexit-Handler nur einmal registrieren
atexit.register(thread_manager.shutdown_all) atexit.register(thread_manager.shutdown_all)
_windows_fixes_applied = True
windows_logger.info("✅ Alle Windows-Fixes erfolgreich angewendet") windows_logger.info("✅ Alle Windows-Fixes erfolgreich angewendet")
# Automatisch Windows-Fixes beim Import anwenden # Automatisch Windows-Fixes beim Import anwenden (nur einmal)
if os.name == 'nt': if os.name == 'nt' and not _windows_fixes_applied:
apply_all_windows_fixes() apply_all_windows_fixes()