Wrap stdout/stderr.flush() in sync_write with try/except OSError

The flush() method on lines 366-379 already catches OSError and ValueError
when calling original_stdout.flush() / original_stderr.flush(), but the
sync_write() method on line 361 and the tqdm branch in write() on line 336
do NOT. On Windows, when ComfyUI is launched as a child process with piped
stdio, certain conditions can leave the underlying handle in a state where
flush() raises OSError [Errno 22] Invalid argument.

Once that happens, the unhandled OSError propagates back through:
  print() in any custom node
  -> write(message) in this logger wrapper
  -> sync_write(message)
  -> original_*.flush()
  -> OSError [Errno 22]

This kills prompt execution for any custom node that prints during
INPUT_TYPES() or __init__ -- even on a benign log line like
'Dependencies already installed from previous run' in LatentSyncWrapper.

Symptoms users will recognize:
- LatentSync, Sonic, Hallo 2 all failing with [Errno 22] before reading inputs
- 'Logging error' lines spammed throughout the console
- The error in the user's traceback always points back to
  prestartup_script.py:361 / app/logger.py:35 super().flush()

Wrapping the flush calls in try/except (OSError, ValueError) -- the
exact same pattern already used in self.flush() on line 378 -- breaks
the cascade. Print failures degrade silently to file-only logging
instead of taking down prompt execution.
This commit is contained in:
Any Name 2026-04-18 19:26:37 -07:00
parent 22fc850853
commit 5ea9410914

View File

@ -332,8 +332,14 @@ try:
if '100%' in message:
self.sync_write(message)
else:
write_stderr(message)
original_stderr.flush()
# Wrap flush() to match the safer behaviour of
# self.flush() below — a broken pipe must not
# kill the calling print() (and thus the node).
try:
write_stderr(message)
original_stderr.flush()
except (OSError, ValueError):
pass
else:
self.sync_write(message)
else:
@ -356,12 +362,20 @@ try:
if not file_only:
with std_log_lock:
if self.is_stdout:
write_stdout(message)
original_stdout.flush()
else:
write_stderr(message)
original_stderr.flush()
# Wrap flush() in try/except to match self.flush()
# below. Without this, an OSError from a broken
# stdio pipe (e.g. Windows [Errno 22] Invalid argument)
# propagates up through every print() call in every
# custom node, killing prompt execution.
try:
if self.is_stdout:
write_stdout(message)
original_stdout.flush()
else:
write_stderr(message)
original_stderr.flush()
except (OSError, ValueError):
pass
def flush(self):
try: