fix(exit): stop running jobs before Python joins the executor threads (#376)

ComfyUI returns from main.py after Ctrl+C without closing its event loop,
and Python joins every executor thread before any atexit callback runs, so
a scan batch, thumbnail batch or model download in flight kept ComfyUI
alive until it ended (on Windows each ffmpeg up to its 30 s timeout).

The package now registers a threading._register_atexit hook (after
concurrent.futures', so it runs before that join) that sets an exit signal
and kills the running encoder processes. Job.cancelled follows the signal,
so every check a job already makes between files stops it at exit;
map_parallel starts no further item, the scan walk stops between folders and
a tagging model download stops before its next chunk. Without the internal
hook exit behaves as before.
This commit is contained in:
Vito Sansevero
2026-10-27 19:23:07 -07:00
parent 44177974cb
commit 2c1e401d86
9 changed files with 618 additions and 2 deletions
+7
View File
@@ -92,6 +92,11 @@ try:
except ImportError: # tests import the package top-level
from utils.parallel import map_parallel
try:
from ...utils.exit_signal import ExitRequested
except ImportError: # tests import the package top-level
from utils.exit_signal import ExitRequested
# The placeholder frame a video without a preview is answered with (JPEG
# bytes, never written to disk); written previews follow the settings.
PLACEHOLDER_SIZE = (thumbnail_settings.DEFAULT_EDGE, thumbnail_settings.DEFAULT_EDGE)
@@ -448,6 +453,8 @@ class AutoThumbnailer:
def _run(self):
try:
self._drain()
except ExitRequested:
pass # #376: the interpreter is exiting; queued files are dropped
except Exception:
self._logger.warning("The automatic preview worker stopped", exc_info=True)
finally: