Skip to content

Commit 71e86f4

Browse files
Fix memory leaks in process management (#224)
* Update default formatter * Fix memory leaks in process management Memory leaks occurred from three sources: event listeners accumulated when log streaming was cancelled, completed processes remained in memory indefinitely, and Durable Object state retained invalid references after container restarts. The ProcessStore now persists completed processes to disk while keeping active processes in memory. ReadableStream cancel handlers properly remove listeners when log streaming stops. The Sandbox onStop lifecycle hook clears container-specific state to prevent stale references. * Add changeset * Fix async cleanup and listener lifecycle The onStop lifecycle hook now properly awaits storage deletions to ensure cleanup completes before shutdown. Processes are deleted from memory before persisting to disk to prevent race conditions during concurrent access. Stream listeners are cleaned up on all close paths, not just cancellation. The list method now scans disk to include completed processes, maintaining backward compatibility. * Use structured logging for disk write failures * Fix data loss when persisting completed processes Write to disk before deleting from memory to prevent data loss if write fails. Always delete from memory regardless of write success to prevent memory leaks. * Fix list() directory check that prevented disk scanning Bun.file().exists() returns false for directories, causing list() to skip disk scanning and miss completed processes. Remove the directory existence check and rely on error handling instead. * Add comprehensive unit tests for ProcessStore Test coverage for memory/disk hybrid storage, terminal state transitions, disk persistence, write failure handling, and list() filtering. * Add E2E tests for completed process retrieval and listing Verify completed processes can be retrieved via get() with exit codes and timestamps, and that list() includes both running and completed processes. * Remove dot-prefix from process storage directory Change from /tmp/.sandbox-internal to /tmp/sandbox-internal for better debuggability. Makes it easier to discover and inspect process files during development and troubleshooting. * Fix race condition in process status updates Event handler called store.update() fire-and-forget, causing API queries to return stale data before disk writes completed. Changed SessionManager to accept async callbacks and await them, ensuring store updates complete before processing next event. This provides strong consistency while maintaining the memory leak fix that moves completed processes to disk. * Update lockfile * Clear activeMounts on container stop Applies memory leak prevention from this PR to the activeMounts feature that was merged from main. When a container stops or restarts, mount points become invalid but the Map still held stale references. Clearing it maintains consistency with portTokens and defaultSession. * Enable TypeScript checking for test files (#238) * Enable TypeScript checking for test files * Enable TypeScript checking for e2e tests Added tests/e2e/ to typecheck pipeline. Created test-worker/types.ts defining response types for test infrastructure endpoints. All tests now use proper SDK types from @repo/shared for SDK operations and test-worker types for test infrastructure. Removed non-null assertions with proper type guards. Found and fixed bugs where tests used wrong field names (contextId vs id, processId vs id) that were masked by inline types. * Fix incorrect assertions * Use public Process interface correctly * Revert enum usage * Enrich interpreter error * Fix TypeScript build output paths Build output was going to dist/src/ instead of dist/ due to rootDir: "." in tsconfig, breaking Docker container startup which expects dist/index.js. Split tsconfig into separate build and typecheck configs. Build emits src only to dist/, typecheck includes tests. * Fix type errors * Update lockfile * Fix code context e2e response checks * Prevent just-completed process appearing twice
1 parent ac185f1 commit 71e86f4

File tree

64 files changed

+2453
-1891
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2453
-1891
lines changed

.changeset/fix-memory-leaks.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cloudflare/sandbox': patch
3+
---
4+
5+
Fix memory leaks from listener accumulation, unbounded process storage, and stale DO state

.vscode/settings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"[javascript]": {
3-
"editor.defaultFormatter": "biomejs.biome"
3+
"editor.defaultFormatter": "esbenp.prettier-vscode"
44
},
55
"[json]": {
6-
"editor.defaultFormatter": "biomejs.biome"
6+
"editor.defaultFormatter": "esbenp.prettier-vscode"
77
},
88
"[typescript]": {
9-
"editor.defaultFormatter": "biomejs.biome"
9+
"editor.defaultFormatter": "esbenp.prettier-vscode"
1010
},
1111
"editor.codeActionsOnSave": {
1212
"source.fixAll.biome": "explicit",

0 commit comments

Comments
 (0)