mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-08-17 20:31:20 +02:00
WebUI: Stability fix, to avoid zombie processes hanging around occasionally after closing Easy Diffusion
This commit is contained in:
@ -6,6 +6,7 @@ from threading import local
|
|||||||
import psutil
|
import psutil
|
||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
|
import atexit
|
||||||
|
|
||||||
from easydiffusion.app import ROOT_DIR, getConfig
|
from easydiffusion.app import ROOT_DIR, getConfig
|
||||||
from easydiffusion.model_manager import get_model_dirs
|
from easydiffusion.model_manager import get_model_dirs
|
||||||
@ -62,6 +63,7 @@ WEBUI_PATCHES = [
|
|||||||
"forge_model_crash_recovery.patch",
|
"forge_model_crash_recovery.patch",
|
||||||
"forge_api_refresh_text_encoders.patch",
|
"forge_api_refresh_text_encoders.patch",
|
||||||
"forge_loader_force_gc.patch",
|
"forge_loader_force_gc.patch",
|
||||||
|
"forge_monitor_parent_process.patch",
|
||||||
]
|
]
|
||||||
|
|
||||||
backend_process = None
|
backend_process = None
|
||||||
@ -188,6 +190,10 @@ def start_backend():
|
|||||||
print("starting", cmd, WEBUI_DIR)
|
print("starting", cmd, WEBUI_DIR)
|
||||||
backend_process = run_in_conda([cmd], cwd=WEBUI_DIR, env=env, wait=False, output_prefix="[WebUI] ")
|
backend_process = run_in_conda([cmd], cwd=WEBUI_DIR, env=env, wait=False, output_prefix="[WebUI] ")
|
||||||
|
|
||||||
|
# atexit.register isn't 100% reliable, that's why we also use `forge_monitor_parent_process.patch`
|
||||||
|
# which causes Forge to kill itself if the parent pid passed to it is no longer valid.
|
||||||
|
atexit.register(backend_process.terminate)
|
||||||
|
|
||||||
restart_if_dead_thread = threading.Thread(target=restart_if_webui_dies_after_starting)
|
restart_if_dead_thread = threading.Thread(target=restart_if_webui_dies_after_starting)
|
||||||
restart_if_dead_thread.start()
|
restart_if_dead_thread.start()
|
||||||
|
|
||||||
@ -366,7 +372,7 @@ def get_env():
|
|||||||
"TRANSFORMERS_CACHE": [f"{dir}/transformers-cache"],
|
"TRANSFORMERS_CACHE": [f"{dir}/transformers-cache"],
|
||||||
"HF_HUB_DISABLE_SYMLINKS_WARNING": ["true"],
|
"HF_HUB_DISABLE_SYMLINKS_WARNING": ["true"],
|
||||||
"COMMANDLINE_ARGS": [
|
"COMMANDLINE_ARGS": [
|
||||||
f'--api --models-dir "{models_dir}" {model_path_args} --skip-torch-cuda-test --disable-gpu-warning --port {impl.WEBUI_PORT}'
|
f'--parent-pid {os.getpid()} --api --models-dir "{models_dir}" {model_path_args} --skip-torch-cuda-test --disable-gpu-warning --port {impl.WEBUI_PORT}'
|
||||||
],
|
],
|
||||||
"SKIP_VENV": ["1"],
|
"SKIP_VENV": ["1"],
|
||||||
"SD_WEBUI_RESTARTING": ["1"],
|
"SD_WEBUI_RESTARTING": ["1"],
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
diff --git a/launch.py b/launch.py
|
||||||
|
index c0568c7b..3919f7dd 100644
|
||||||
|
--- a/launch.py
|
||||||
|
+++ b/launch.py
|
||||||
|
@@ -2,6 +2,7 @@
|
||||||
|
# faulthandler.enable()
|
||||||
|
|
||||||
|
from modules import launch_utils
|
||||||
|
+from modules import parent_process_monitor
|
||||||
|
|
||||||
|
args = launch_utils.args
|
||||||
|
python = launch_utils.python
|
||||||
|
@@ -28,6 +29,10 @@ start = launch_utils.start
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
+ if args.parent_pid != -1:
|
||||||
|
+ print(f"Monitoring parent process for termination. Parent PID: {args.parent_pid}")
|
||||||
|
+ parent_process_monitor.start_monitor_thread(args.parent_pid)
|
||||||
|
+
|
||||||
|
if args.dump_sysinfo:
|
||||||
|
filename = launch_utils.dump_sysinfo()
|
||||||
|
|
||||||
|
diff --git a/modules/cmd_args.py b/modules/cmd_args.py
|
||||||
|
index fcd8a50f..7f684bec 100644
|
||||||
|
--- a/modules/cmd_args.py
|
||||||
|
+++ b/modules/cmd_args.py
|
||||||
|
@@ -148,3 +148,6 @@ parser.add_argument(
|
||||||
|
help="Path to directory with annotator model directories",
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
+
|
||||||
|
+# Easy Diffusion arguments
|
||||||
|
+parser.add_argument("--parent-pid", type=int, default=-1, help='parent process id, if running webui as a sub-process')
|
||||||
|
diff --git a/modules/parent_process_monitor.py b/modules/parent_process_monitor.py
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..cc3e2049
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/modules/parent_process_monitor.py
|
||||||
|
@@ -0,0 +1,45 @@
|
||||||
|
+# monitors and kills itself when the parent process dies. required when running Forge as a sub-process.
|
||||||
|
+# modified version of https://stackoverflow.com/a/23587108
|
||||||
|
+
|
||||||
|
+import sys
|
||||||
|
+import os
|
||||||
|
+import threading
|
||||||
|
+import platform
|
||||||
|
+import time
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _monitor_parent_posix(parent_pid):
|
||||||
|
+ print(f"Monitoring parent pid: {parent_pid}")
|
||||||
|
+ while True:
|
||||||
|
+ if os.getppid() != parent_pid:
|
||||||
|
+ os._exit(0)
|
||||||
|
+ time.sleep(1)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _monitor_parent_windows(parent_pid):
|
||||||
|
+ from ctypes import WinDLL, WinError
|
||||||
|
+ from ctypes.wintypes import DWORD, BOOL, HANDLE
|
||||||
|
+
|
||||||
|
+ SYNCHRONIZE = 0x00100000 # Magic value from http://msdn.microsoft.com/en-us/library/ms684880.aspx
|
||||||
|
+ kernel32 = WinDLL("kernel32.dll")
|
||||||
|
+ kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
|
||||||
|
+ kernel32.OpenProcess.restype = HANDLE
|
||||||
|
+
|
||||||
|
+ handle = kernel32.OpenProcess(SYNCHRONIZE, False, parent_pid)
|
||||||
|
+ if not handle:
|
||||||
|
+ raise WinError()
|
||||||
|
+
|
||||||
|
+ # Wait until parent exits
|
||||||
|
+ from ctypes import windll
|
||||||
|
+
|
||||||
|
+ print(f"Monitoring parent pid: {parent_pid}")
|
||||||
|
+ windll.kernel32.WaitForSingleObject(handle, -1)
|
||||||
|
+ os._exit(0)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def start_monitor_thread(parent_pid):
|
||||||
|
+ if platform.system() == "Windows":
|
||||||
|
+ t = threading.Thread(target=_monitor_parent_windows, args=(parent_pid,), daemon=True)
|
||||||
|
+ else:
|
||||||
|
+ t = threading.Thread(target=_monitor_parent_posix, args=(parent_pid,), daemon=True)
|
||||||
|
+ t.start()
|
Reference in New Issue
Block a user