mirror of
https://github.com/Comfy-Org/comfy-aimdo.git
synced 2026-11-04 23:37:21 +00:00
[GH-ISSUE #125] malloc_graph_destroy() stack-overflows on deep allocation graphs (Windows 1 MB stack), cleanup aborts, next run crashes with 0xC0000005 #47
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-aimdo#47
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @shellddd on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/Comfy-Org/comfy-aimdo/issues/125
Summary
On Windows,
malloc_graph_destroy()recurses once per recorded allocation (free_events()andmaterialize()are both recursive). For large graphs — e.g. a 104k-token attention in a videomodel — the event chain is deep enough to exhaust the default 1 MB thread stack
(
STATUS_STACK_OVERFLOW, 0xC00000FD).Because the call is made from
MallocGraph.__del__, CPython swallows the failure(
Exception ignored in: <function MallocGraph.__del__>), so the graph is left half destroyed:its
physical_page_unref()/virtual_range_unref()calls never run. The next large model runthen crashes with
0xC0000005insideaimdo.dll.So the observable failure is: one prompt finishes "successfully" with a swallowed stack
overflow at teardown, and the next prompt dies with an access violation.
Environment
Reproduction
Workflow: MiniMax H3 video model, 832x480, dynamic VRAM on,
--fast-disk,ComfyUI's model compiler enabled (default).
but the log shows at teardown:
Windows event log:
Observed 3 times across different sessions, always with the same shape:
a swallowed
stack overflowat teardown, then0xC0000005on the next ≥90k-token run.Runs below ~65k tokens never crash, even when repeated dozens of times in one process.
Root cause (from source)
src/malloc-graph.c:This builds a linear chain of events, one per recorded allocation, so the tree depth equals the
number of allocations recorded for the run.
Both teardown paths then recurse along that chain:
scrub_rogue_snapshots()recurses over the same tree as well.malloc_graph_destroy()runsabort_graph()(which callsmaterialize()), thenfree_events(). On Windows the thread stack (the prompt worker thread created bythreading.Thread) is 1 MB. A large video/attention graph records tens of thousands ofallocations, so the recursion blows the stack.
When that happens inside
__del__, theOSError: exception: stack overflowis swallowed byCPython, so:
free_events()only freed the events below the failing frame,physical_page_unref()loop overmapped_pages/physical_pages/small_*never runs,virtual_range_unref(g->base)/virtual_range_unref(g->small_base)never run(each graph reserves
MG_PAGES = 8192× 8 MiB = 64 GiB of VA plus 8 GiB for small pages).The leaked/partially torn-down graph then poisons the next large allocation, producing the
0xC0000005insideaimdo.dll.Suggested fix
Convert the three recursive walkers to explicit-stack loops. Sketch for
free_events():materialize(g, event)needs the chain collected into an array first (walkevent->previousto the snapshot/root), then applied top-down — again no recursion.scrub_rogue_snapshots()is the same tree walk with an explicit stack.Even simpler defensive measure: if the graph's event count is huge, do the destroy work on a
worker thread with a large stack, or bail out of
destroy()before touching the tree and handthe VRAM back through the existing rogue-candidate path.
Workarounds we use on our side
--disable-comfy-compiler(no graph recorded at all), orthreading.stack_size(64 << 20)), which multiplied theusable depth ~60×, or
Attachments
Happy to attach full
comfyui.log+ launcher diagnostic bundles for all three crashes(python 3.13.11, torch 2.9.1+cu130, driver 610.88) if useful.
Related but different: #48 is
0xC00000FDat startup on 0.2.14; this one is a runtimestack overflow during graph teardown on large graphs, only after ≥90k-token runs.