diff --git a/backend/app/database/myp.db-shm b/backend/app/database/myp.db-shm index 37569ebd..02044429 100644 Binary files a/backend/app/database/myp.db-shm and b/backend/app/database/myp.db-shm differ diff --git a/backend/app/database/myp.db-wal b/backend/app/database/myp.db-wal index 3cf424f0..c92a0359 100644 Binary files a/backend/app/database/myp.db-wal and b/backend/app/database/myp.db-wal differ diff --git a/backend/app/utils/windows_fixes.py b/backend/app/utils/windows_fixes.py index 4c1be66f..0bf89e63 100644 --- a/backend/app/utils/windows_fixes.py +++ b/backend/app/utils/windows_fixes.py @@ -15,6 +15,23 @@ from utils.logging_config import get_logger # Logger für Windows-Fixes windows_logger = get_logger("windows_fixes") +# Exportierte Funktionen +__all__ = [ + 'WindowsThreadManager', + 'get_windows_thread_manager', + 'fix_windows_socket_issues', + 'apply_safe_socket_options', + 'setup_windows_environment', + 'is_flask_reloader_process', + 'apply_all_windows_fixes', + 'safe_subprocess_run', + 'patch_subprocess', + 'apply_global_subprocess_patch', + 'apply_encoding_fixes', + 'apply_threading_fixes', + 'apply_signal_fixes' +] + # Globale Flags um doppelte Anwendung zu verhindern _windows_fixes_applied = False _socket_patches_applied = False @@ -205,153 +222,6 @@ def is_flask_reloader_process() -> bool: """ return os.environ.get('WERKZEUG_RUN_MAIN') != 'true' -def apply_all_windows_fixes(): - """Wendet alle Windows-spezifischen Fixes an.""" - global _windows_fixes_applied - - if _windows_fixes_applied: - return - - try: - windows_logger.info("🔧 Wende Windows-spezifische Fixes an...") - - # 1. Encoding-Fixes - apply_encoding_fixes() - - # 2. Threading-Fixes - apply_threading_fixes() - - # 3. Signal-Handler-Fixes - apply_signal_fixes() - - # 4. Subprocess-Patch für UTF-8 Encoding - patch_subprocess() - - # 5. Globaler Subprocess-Patch für bereits importierte Module - apply_global_subprocess_patch() - - _windows_fixes_applied = True - windows_logger.info("✅ Alle Windows-Fixes erfolgreich angewendet") - - except Exception as e: - windows_logger.error(f"❌ Fehler beim Anwenden der Windows-Fixes: {str(e)}") - raise e - -# Automatisch Windows-Fixes beim Import anwenden (nur einmal) -if os.name == 'nt' and not _windows_fixes_applied: - # Sehr früher subprocess-Patch für sofortige Wirkung - try: - import subprocess - if not hasattr(subprocess, '_early_patched'): - patch_subprocess() - subprocess._early_patched = True - windows_logger.info("✅ Früher subprocess-Patch beim Import angewendet") - except Exception as e: - windows_logger.warning(f"⚠️ Früher subprocess-Patch fehlgeschlagen: {str(e)}") - - apply_all_windows_fixes() - -# ===== SICHERE SUBPROCESS-WRAPPER ===== - -def safe_subprocess_run(*args, **kwargs): - """ - Sicherer subprocess.run Wrapper für Windows mit UTF-8 Encoding. - Verhindert charmap-Fehler durch explizite Encoding-Einstellungen. - """ - import subprocess - - # Standard-Encoding für Windows setzen - if 'encoding' not in kwargs and kwargs.get('text', False): - kwargs['encoding'] = 'utf-8' - kwargs['errors'] = 'replace' - - # Timeout-Standard setzen falls nicht vorhanden - if 'timeout' not in kwargs: - kwargs['timeout'] = 30 - - try: - return subprocess.run(*args, **kwargs) - except subprocess.TimeoutExpired as e: - logger.warning(f"Subprocess-Timeout nach {kwargs.get('timeout', 30)}s: {' '.join(args[0]) if args and isinstance(args[0], list) else str(args)}") - raise e - except UnicodeDecodeError as e: - logger.error(f"Unicode-Decode-Fehler in subprocess: {str(e)}") - # Fallback ohne text=True - kwargs_fallback = kwargs.copy() - kwargs_fallback.pop('text', None) - kwargs_fallback.pop('encoding', None) - kwargs_fallback.pop('errors', None) - return subprocess.run(*args, **kwargs_fallback) - except Exception as e: - logger.error(f"Subprocess-Fehler: {str(e)}") - raise e - -# ===== SUBPROCESS-MONKEY-PATCH ===== - -def patch_subprocess(): - """ - Patcht subprocess.run und subprocess.Popen um automatisch sichere Encoding-Einstellungen zu verwenden. - """ - import subprocess - - # Original-Funktionen speichern - if not hasattr(subprocess, '_original_run'): - subprocess._original_run = subprocess.run - subprocess._original_popen = subprocess.Popen - - def patched_run(*args, **kwargs): - # Automatisch UTF-8 Encoding für text=True setzen - if kwargs.get('text', False) and 'encoding' not in kwargs: - kwargs['encoding'] = 'utf-8' - kwargs['errors'] = 'replace' - - return subprocess._original_run(*args, **kwargs) - - def patched_popen(*args, **kwargs): - # Automatisch UTF-8 Encoding für text=True setzen - if kwargs.get('text', False) and 'encoding' not in kwargs: - kwargs['encoding'] = 'utf-8' - kwargs['errors'] = 'replace' - - # Auch für universal_newlines (ältere Python-Versionen) - if kwargs.get('universal_newlines', False) and 'encoding' not in kwargs: - kwargs['encoding'] = 'utf-8' - kwargs['errors'] = 'replace' - - return subprocess._original_popen(*args, **kwargs) - - subprocess.run = patched_run - subprocess.Popen = patched_popen - logger.info("✅ Subprocess automatisch gepatcht für UTF-8 Encoding (run + Popen)") - -# ===== GLOBALER SUBPROCESS-PATCH ===== - -def apply_global_subprocess_patch(): - """ - Wendet den subprocess-Patch global an, auch für bereits importierte Module. - """ - import sys - import subprocess - - # Patch subprocess direkt - patch_subprocess() - - # Patch auch in bereits importierten Modulen - for module_name, module in sys.modules.items(): - if hasattr(module, 'subprocess') and module.subprocess is subprocess: - # Modul verwendet subprocess - patch es - module.subprocess = subprocess - logger.debug(f"✅ Subprocess in Modul {module_name} gepatcht") - - logger.info("✅ Globaler subprocess-Patch angewendet") - -# ===== EXPORT SAFE SUBPROCESS ===== - -# Sichere subprocess-Funktion exportieren -__all__.append('safe_subprocess_run') -__all__.append('patch_subprocess') -__all__.append('apply_global_subprocess_patch') - # ===== ENCODING-FIXES ===== def apply_encoding_fixes(): @@ -392,4 +262,137 @@ def apply_signal_fixes(): windows_logger.debug("✅ Windows-Signal-Fixes angewendet") except Exception as e: - windows_logger.warning(f"⚠️ Signal-Fixes konnten nicht angewendet werden: {str(e)}") \ No newline at end of file + windows_logger.warning(f"⚠️ Signal-Fixes konnten nicht angewendet werden: {str(e)}") + +# ===== SICHERE SUBPROCESS-WRAPPER ===== + +def safe_subprocess_run(*args, **kwargs): + """ + Sicherer subprocess.run Wrapper für Windows mit UTF-8 Encoding. + Verhindert charmap-Fehler durch explizite Encoding-Einstellungen. + """ + import subprocess + + # Standard-Encoding für Windows setzen + if 'encoding' not in kwargs and kwargs.get('text', False): + kwargs['encoding'] = 'utf-8' + kwargs['errors'] = 'replace' + + # Timeout-Standard setzen falls nicht vorhanden + if 'timeout' not in kwargs: + kwargs['timeout'] = 30 + + try: + return subprocess.run(*args, **kwargs) + except subprocess.TimeoutExpired as e: + windows_logger.warning(f"Subprocess-Timeout nach {kwargs.get('timeout', 30)}s: {' '.join(args[0]) if args and isinstance(args[0], list) else str(args)}") + raise e + except UnicodeDecodeError as e: + windows_logger.error(f"Unicode-Decode-Fehler in subprocess: {str(e)}") + # Fallback ohne text=True + kwargs_fallback = kwargs.copy() + kwargs_fallback.pop('text', None) + kwargs_fallback.pop('encoding', None) + kwargs_fallback.pop('errors', None) + return subprocess.run(*args, **kwargs_fallback) + except Exception as e: + windows_logger.error(f"Subprocess-Fehler: {str(e)}") + raise e + +# ===== SUBPROCESS-MONKEY-PATCH ===== + +def patch_subprocess(): + """ + Patcht subprocess.run und subprocess.Popen um automatisch sichere Encoding-Einstellungen zu verwenden. + """ + import subprocess + + # Original-Funktionen speichern + if not hasattr(subprocess, '_original_run'): + subprocess._original_run = subprocess.run + subprocess._original_popen = subprocess.Popen + + def patched_run(*args, **kwargs): + # Automatisch UTF-8 Encoding für text=True setzen + if kwargs.get('text', False) and 'encoding' not in kwargs: + kwargs['encoding'] = 'utf-8' + kwargs['errors'] = 'replace' + + return subprocess._original_run(*args, **kwargs) + + def patched_popen(*args, **kwargs): + # Automatisch UTF-8 Encoding für text=True setzen + if kwargs.get('text', False) and 'encoding' not in kwargs: + kwargs['encoding'] = 'utf-8' + kwargs['errors'] = 'replace' + + # Auch für universal_newlines (ältere Python-Versionen) + if kwargs.get('universal_newlines', False) and 'encoding' not in kwargs: + kwargs['encoding'] = 'utf-8' + kwargs['errors'] = 'replace' + + return subprocess._original_popen(*args, **kwargs) + + subprocess.run = patched_run + subprocess.Popen = patched_popen + windows_logger.info("✅ Subprocess automatisch gepatcht für UTF-8 Encoding (run + Popen)") + +# ===== GLOBALER SUBPROCESS-PATCH ===== + +def apply_global_subprocess_patch(): + """ + Wendet den subprocess-Patch global an, auch für bereits importierte Module. + """ + import sys + import subprocess + + # Patch subprocess direkt + patch_subprocess() + + # Patch auch in bereits importierten Modulen + for module_name, module in sys.modules.items(): + if hasattr(module, 'subprocess') and module.subprocess is subprocess: + # Modul verwendet subprocess - patch es + module.subprocess = subprocess + windows_logger.debug(f"✅ Subprocess in Modul {module_name} gepatcht") + + windows_logger.info("✅ Globaler subprocess-Patch angewendet") + +def apply_all_windows_fixes(): + """Wendet alle Windows-spezifischen Fixes an.""" + global _windows_fixes_applied + + if _windows_fixes_applied: + return + + try: + windows_logger.info("🔧 Wende Windows-spezifische Fixes an...") + + # 1. Encoding-Fixes + apply_encoding_fixes() + + # 2. Threading-Fixes + apply_threading_fixes() + + # 3. Signal-Handler-Fixes + apply_signal_fixes() + + # 4. Subprocess-Patch für UTF-8 Encoding + patch_subprocess() + + # 5. Globaler Subprocess-Patch für bereits importierte Module + apply_global_subprocess_patch() + + _windows_fixes_applied = True + windows_logger.info("✅ Alle Windows-Fixes erfolgreich angewendet") + + except Exception as e: + windows_logger.error(f"❌ Fehler beim Anwenden der Windows-Fixes: {str(e)}") + raise e + +# Automatisch Windows-Fixes beim Import anwenden (nur einmal) +if os.name == 'nt' and not _windows_fixes_applied: + try: + apply_all_windows_fixes() + except Exception as e: + windows_logger.warning(f"⚠️ Windows-Fixes konnten nicht automatisch angewendet werden: {str(e)}") \ No newline at end of file