mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
## Summary - Fixed allocator threading violation when `BUN_INSPECT_CONNECT_TO` is set - Created thread-local `env_loader` with proper allocator isolation in debugger thread - Added regression test to verify the fix works correctly ## Problem When `BUN_INSPECT_CONNECT_TO` environment variable is set, Bun creates a debugger thread that spawns its own `VirtualMachine` instance. Previously, this VM would fall back to the global `DotEnv.instance` which was created with the main thread's allocator, causing threading violations when the debugger thread accessed environment files via `--env-file` or other env loading operations. ## Solution Modified `startJSDebuggerThread` in `src/bun.js/Debugger.zig` to: 1. Create a thread-local `DotEnv.Map` and `DotEnv.Loader` using the debugger thread's allocator 2. Pass this thread-local `env_loader` to `VirtualMachine.init()` to ensure proper allocator isolation 3. Prevent sharing of allocators across threads ## Test plan - [x] Added regression test in `test/regression/issue/test_env_loader_threading.test.ts` - [x] Verified basic Bun functionality still works - [x] Test passes with both normal execution and with `BUN_INSPECT_CONNECT_TO` set 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
import { spawn } from "bun";
|
|
import { expect, test } from "bun:test";
|
|
import { bunExe, tempDirWithFiles } from "harness";
|
|
|
|
test("env_loader should not have allocator threading issues with BUN_INSPECT_CONNECT_TO", async () => {
|
|
const dir = tempDirWithFiles("env-loader-threading", {
|
|
".env": "TEST_ENV_VAR=hello_world",
|
|
"index.js": `console.log(process.env.TEST_ENV_VAR || 'undefined');`,
|
|
});
|
|
|
|
// This test verifies that when BUN_INSPECT_CONNECT_TO is set,
|
|
// the debugger thread creates its own env_loader with proper allocator isolation
|
|
// and doesn't cause threading violations when accessing environment files.
|
|
|
|
// First, test normal execution without inspector to establish baseline
|
|
const normalProc = spawn({
|
|
cmd: [bunExe(), "index.js"],
|
|
cwd: dir,
|
|
env: {
|
|
...Bun.env,
|
|
TEST_ENV_VAR: undefined, // Remove from process env to test .env loading
|
|
},
|
|
stdio: ["inherit", "pipe", "pipe"],
|
|
});
|
|
|
|
const normalResult = await normalProc.exited;
|
|
const normalStdout = await normalProc.stdout.text();
|
|
|
|
expect(normalResult).toBe(0);
|
|
expect(normalStdout.trim()).toBe("hello_world");
|
|
|
|
// Now test with BUN_INSPECT_CONNECT_TO set to a non-existent socket
|
|
// This should trigger the debugger thread creation without actually connecting
|
|
const inspectorProc = spawn({
|
|
cmd: [bunExe(), "index.js"],
|
|
cwd: dir,
|
|
env: {
|
|
...Bun.env,
|
|
BUN_INSPECT_CONNECT_TO: "/tmp/non-existent-debug-socket",
|
|
TEST_ENV_VAR: undefined, // Remove from process env to test .env loading
|
|
},
|
|
stdio: ["inherit", "pipe", "pipe"],
|
|
});
|
|
|
|
const inspectorResult = await inspectorProc.exited;
|
|
const inspectorStdout = await inspectorProc.stdout.text();
|
|
const inspectorStderr = await inspectorProc.stderr.text();
|
|
|
|
// The process should still work correctly and load .env file
|
|
expect(inspectorResult).toBe(0);
|
|
expect(inspectorStdout.trim()).toBe("hello_world");
|
|
|
|
// Should not have any allocator-related errors or panics
|
|
expect(inspectorStderr).not.toContain("panic");
|
|
expect(inspectorStderr).not.toContain("allocator");
|
|
expect(inspectorStderr).not.toContain("thread");
|
|
expect(inspectorStderr).not.toContain("assertion failed");
|
|
}, 10000); // 10 second timeout for potential debugger connection attempts
|