From 97ed41c345688a8ad7f93cc51b5a0df8e977a390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Piotte?= Date: Sat, 9 May 2026 20:14:17 -0400 Subject: [PATCH] Fix Extract hanging on progress dialog when config dir is missing The Extract flow builds an .ini path under /.ini, but only the parent of was being created, so opening the .ini for write raised FileNotFoundError. The exception killed the worker thread before ProgressBar.End() ran, leaving the "Downloading" dialog visible forever and the UI unresponsive. - FileManager.submit: ensure os.path.dirname(configFile) exists right before opening it for write, so the actual containing directory is created (not just its parent). - ProgressBar.Run: wrap the task callable in a try/except that schedules Destroy on the Tk thread if the worker crashes, so any future thread fault closes the progress window instead of hanging the UI. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/modules/FrontEnd/ProgressBar.py | 11 +++++++++-- src/modules/GameManager/FileManager.py | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/FrontEnd/ProgressBar.py b/src/modules/FrontEnd/ProgressBar.py index 9820ba3..b468b46 100644 --- a/src/modules/FrontEnd/ProgressBar.py +++ b/src/modules/FrontEnd/ProgressBar.py @@ -32,8 +32,15 @@ def Run(cls, window, tasks): label.pack(pady=10) cls.progress_bar = ttk.Progressbar(cls.progress_window, mode="determinate", maximum=total_iterations) cls.progress_bar.pack(pady=20) - task_thread = threading.Thread(target=tasks) - task_thread.start() + def _safe_tasks(): + try: + tasks() + except Exception as e: + log.error(f"Task thread crashed: {e!r}") + cls.progress_window.after(0, cls.Destroy) + + task_thread = threading.Thread(target=_safe_tasks) + task_thread.start() @classmethod def Destroy(cls): diff --git a/src/modules/GameManager/FileManager.py b/src/modules/GameManager/FileManager.py index ba438b2..6471e4b 100644 --- a/src/modules/GameManager/FileManager.py +++ b/src/modules/GameManager/FileManager.py @@ -545,6 +545,8 @@ def Create_Mod_Patch(mode: str | None = None): else: configFile = ini_file_path ## compatibility for old patches + os.makedirs(os.path.dirname(configFile), exist_ok=True) + if os.path.exists(configFile): config.read(configFile, encoding="utf-8")