Fix Windows deadlock: decode extension subprocess pipes as UTF-8 - #282
Fix Windows deadlock: decode extension subprocess pipes as UTF-8#282OPTI-james wants to merge 3 commits into
Conversation
Modly had no SECURITY.md and no private channel for vulnerability reports, which left email as the only route for researchers. Private vulnerability reporting is now enabled on the repository; this points people at it and sets expectations around it. The policy leads with a threat model and lets the scope follow from it, so that an excluded report comes with the reason it was excluded. Two assumptions are deliberate: workflow files are untrusted input because sharing them is normal, and any web page the user has open is an untrusted caller of the loopback API. The second is why the network-exposure exclusion is narrowed to deliberate exposure only -- a page in the user's own browser needs none. Every claim was checked against the code. The policy does not call the installer signed (no platform signs it), says nothing about PyTorch (we do not ship it), and does not excuse social engineering on the strength of UI warnings that do not exist.
…curity docs: add a security policy with a private reporting route
With bare text=True the host decodes worker stdout/stderr with the locale codec (cp1252 on Windows), which lacks bytes like 0x8f from tqdm's block glyphs. The stderr reader thread then dies with UnicodeDecodeError, the pipe fills, and the worker blocks forever on its next write - generations wedge silently mid-run (and HF weight downloads stall the same way). Decode both pipes as UTF-8 with errors=replace and set PYTHONIOENCODING=utf-8 for the child so both ends of the pipe agree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code reviewFound 1 issue:
PR #272 ("fix(extensions): force UTF-8 stdio on Windows to stop UnicodeEncodeError crashes") already fixed this exact deadlock on Merging this PR as-is (especially now that its base is being switched to modly/api/services/extension_process.py Lines 84 to 92 in 92d4c1b Compare with the existing fix on dev: https://github.com/lightningpixel/modly/blob/dev/api/services/extension_process.py - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Problem
On Windows, extension generations wedge silently mid-run (stuck at ~80%, idle GPU/CPU), and HuggingFace weight downloads stall the same way. Nothing is reported — the run just never finishes.
Root cause
ExtensionProcesslaunches the worker with baretext=True, so the host decodes the worker's stdout/stderr with the locale codec — cp1252 on Windows. The moment the worker prints something cp1252 can't decode (tqdm's block glyphs, e.g.▏=e2 96 8f; byte0x8fis undefined in cp1252), the stderr reader thread dies:With no reader draining the pipe, the OS pipe buffer fills and the worker blocks forever on its next stderr write — deadlocked inside the diffusion loop with no error surfaced. Any tqdm output triggers it, so on Windows this bites on essentially every generation and every in-worker weight download.
Fix
errors="replace"so a stray byte can never kill the reader thread.PYTHONIOENCODING=utf-8for the child (viasetdefault, so an explicit override is respected) so both ends of the pipe agree on the encoding.Verification
Reproduced on Windows 11 with the Hunyuan3D 2 Mini extension (RTX 5060 Ti): before the fix, three consecutive runs wedged at "Generating 3D shape…" (one sat for a full hour). After the fix, live tqdm streams through (
Diffusion Sampling: 3/50, 10.53it/s) and the same run completes in ~80 s. Full test suite passes (npm test: 23 py + 77 node).🤖 Generated with Claude Code