[miniflare] Clean up Containers on shutdown - #15756
ghostwriternr wants to merge 3 commits into
Conversation
SIGKILL is correct for ordinary Workers: dispose and reload should not wait for HTTP connections to drain. Durable Object containers need a different path. workerd can remove the application container and proxy sidecar only during SIGTERM drain, so those runtimes get SIGTERM with a timeout back to SIGKILL. Track disposal with the exact child so concurrent callers and replacements observe one completed termination.
🦋 Changeset detectedLatest commit: 0a5f2c4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 8 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@cloudflare/autoconfig
@cloudflare/build-output-utils
@cloudflare/codemods
@cloudflare/config
@cloudflare/containers-shared
create-cloudflare
@cloudflare/deploy-helpers
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-functions
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-plugin
@cloudflare/workers-auth
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
| void this.#runtime?.disposeImmediately(); | ||
| // This exit hook is synchronous — the event loop will never run again | ||
| // after it returns, so any operation that schedules a microtask (like | ||
| // fs.promises.rm) will never even be executed, let alone completed. | ||
| // We must use the sync variant here. | ||
| // `Runtime#dispose()` should kill the runtime immediately but it might not, | ||
| // so we only clean up on a best effort basis. | ||
| // `Runtime#disposeImmediately()` sends SIGKILL synchronously, but this hook | ||
| // cannot wait for the child to exit, so subsequent cleanup is best-effort. |
There was a problem hiding this comment.
disposeImmediately() forces SIGKILL for every exitHook path. The SIGINT/SIGTERM listeners call this callback before exiting, so Ctrl-C cannot give container-enabled workerd its required SIGTERM drain and managed Docker resources can leak. dispose() sends the appropriate signal synchronously, so it can safely be invoked from this hook.
| void this.#runtime?.disposeImmediately(); | |
| // This exit hook is synchronous — the event loop will never run again | |
| // after it returns, so any operation that schedules a microtask (like | |
| // fs.promises.rm) will never even be executed, let alone completed. | |
| // We must use the sync variant here. | |
| // `Runtime#dispose()` should kill the runtime immediately but it might not, | |
| // so we only clean up on a best effort basis. | |
| // `Runtime#disposeImmediately()` sends SIGKILL synchronously, but this hook | |
| // cannot wait for the child to exit, so subsequent cleanup is best-effort. | |
| void this.#runtime?.dispose(); | |
| // This exit hook is synchronous — the event loop will never run again | |
| // after it returns, so any operation that schedules a microtask (like | |
| // fs.promises.rm) will never even be executed, let alone completed. | |
| // We must use the sync variant here. | |
| // `Runtime#dispose()` sends the shutdown signal synchronously. Container | |
| // runtimes receive SIGTERM to drain managed resources, while ordinary | |
| // runtimes still receive SIGKILL. |
|
I'm Bonk, and I've done a quick review of your PR. Moves Container cleanup responsibility to workerd's managed shutdown path.
|
Wrangler and Vite know which images they prepare, but not every runtime resource workerd creates. Image-tag sweeps can remove the application container while missing proxy sidecars and snapshot volumes. Keep image preparation and awaited Miniflare disposal, remove caller-owned Docker scans, and cover exact application and sidecar cleanup through managed close.
a2b3200 to
0a5f2c4
Compare
Container-backed workerd processes can remove their application containers and proxy sidecars only during graceful shutdown. Miniflare currently terminates every workerd process immediately, while Wrangler and Vite attempt incomplete Docker cleanup from image tags.
Use bounded
SIGTERMshutdown for Container-enabled runtimes, wait for the exact child to exit, and escalate toSIGKILLafter five seconds. Keep ordinary and emergency shutdown immediate. Remove caller-owned Docker sweeps so workerd remains the sole owner of runtime containers, sidecars, snapshot volumes, and cleanup ordering.