fix(cli): robust paste file expansion and process_loop error handling (#17666)
Two narrow fixes for long pasted messages silently disappearing: 1. _expand_paste_references: replace path.exists() + read_text() with try/except (OSError, IOError). Closes the TOCTOU window where a paste file deleted between check and read raised FileNotFoundError, bubbled up through process_loop's outer except, and silently dropped the user's input. Failures now return the placeholder text and log a warning. 2. process_loop outer except: logger.warning() instead of print(). prompt_toolkit's TUI swallows stdout, so 'Error: …' was invisible to the user. Logged errors are discoverable via hermes logs. Dropped the larger interrupt_queue→pending_input drain that was part of the original PR — that's a separate class of input-drop (in-progress interrupt handling) unrelated to the paste-file TOCTOU reported in the issue, and worth its own review. Salvage of #17939.
This commit is contained in:
parent
5eac6084bc
commit
7696ddc59e
11
cli.py
11
cli.py
@ -2928,7 +2928,14 @@ class HermesCLI:
|
|||||||
|
|
||||||
def _expand_ref(match):
|
def _expand_ref(match):
|
||||||
path = Path(match.group(1))
|
path = Path(match.group(1))
|
||||||
return path.read_text(encoding="utf-8") if path.exists() else match.group(0)
|
# Use try/except instead of path.exists() to avoid TOCTOU race:
|
||||||
|
# the paste file may be deleted between check and read, causing
|
||||||
|
# the input to be silently dropped (#17666).
|
||||||
|
try:
|
||||||
|
return path.read_text(encoding="utf-8")
|
||||||
|
except (OSError, IOError):
|
||||||
|
logger.warning("Paste file gone or unreadable, returning placeholder: %s", path)
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
return paste_ref_re.sub(_expand_ref, text)
|
return paste_ref_re.sub(_expand_ref, text)
|
||||||
|
|
||||||
@ -11584,7 +11591,7 @@ class HermesCLI:
|
|||||||
pass # Non-fatal — don't break the main loop
|
pass # Non-fatal — don't break the main loop
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error: {e}")
|
logger.warning("process_loop unhandled error (msg may be lost): %s", e)
|
||||||
|
|
||||||
# Start processing thread
|
# Start processing thread
|
||||||
process_thread = threading.Thread(target=process_loop, daemon=True)
|
process_thread = threading.Thread(target=process_loop, daemon=True)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user