Repository navigation
[Bug] Native HMR starts replacement activation before asynchronous disposal finishes #6883
builtin-pb
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
A live Host reload can start the replacement plugin before the previous instance's asynchronous disposer finishes. A plugin holding an exclusive resource then fails to reactivate even though its disposer eventually releases that resource.
Reproduced directly with DSH 0.1.5-rc.2, Node 24.19.0, macOS ARM64. The attached reproduction invokes the installed DSH entry with native Cordis HMR; it does not use dsh-developer, a browser, a model, or plugin installation.
The fixture acquires a file with
open(path, 'wx'). Itsctx.effect()disposer awaits 200 ms, closes the handle, and unlinks the file. Changing an imported module produces:EEXISTExpected: awaited cleanup finishes before replacement activation reacquires an exclusive resource. Actual: cleanup and replacement activation overlap. This is live reload, separate from SIGTERM or forced process shutdown.
In the installed
@deepseek-ai/cordis-plugin-hmrimplementation,partialReload()callsctx.registry.delete(plugin)and proceeds toreload(...). Cordis registrydelete()starts eachfiber.dispose()without awaiting it. The replacement also takes over the loader entry's current fiber, so awaiting current entries does not establish that the removed fiber has drained. This appears to be the lifecycle handoff that needs attention; I have not implemented an upstream repair.Self-contained reproduction (Node built-ins only)
Save as
native-hmr-disposal.mjs, then run against an installed runtime:The script uses a disposable DSH home, disables browser opening, keeps the lock and trace outside the watched directory, prints the observed ordering, and removes its temporary files after stopping the owned process.
Separate development-wrapper trials observed the same overlap on 0.1.1-rc.2 and 0.1.5-rc.2. The wrapper correctly reported failed activation with one inactive entry; the direct reproduction above isolates the current native runtime behavior. Windows and other versions are not established by these observations.
Until the handoff is resolved, plugins requiring an exclusive resource should restart the process or explicitly coordinate that resource's lifetime. There is no claim here that all plugins fail to reload.
All reactions