mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 13:51:47 +00:00
cleanup debugger file and tests
This commit is contained in:
@@ -319,13 +319,24 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* connection : connections)
|
||||
for (auto* connection : connections) {
|
||||
connection->pauseFlags.store(0);
|
||||
// Reset the scheduled flag so the debugger thread can post new
|
||||
// tasks after the pause loop exits.
|
||||
connection->jsThreadMessageScheduled.store(false);
|
||||
}
|
||||
}
|
||||
|
||||
void receiveMessagesOnInspectorThread(ScriptExecutionContext& context, Zig::GlobalObject* globalObject, bool connectIfNeeded)
|
||||
{
|
||||
this->jsThreadMessageScheduledCount.store(0);
|
||||
// Only clear the scheduled flag when NOT in the pause loop.
|
||||
// During the pause loop, receiveMessagesOnInspectorThread is called
|
||||
// repeatedly by the busy-poll. Clearing the flag would cause the
|
||||
// debugger thread to re-post a task + interruptForMessageDelivery
|
||||
// on every subsequent message, which is wasteful (and the posted
|
||||
// tasks pile up for after the loop exits).
|
||||
if (!(this->pauseFlags.load() & kInPauseLoop))
|
||||
this->jsThreadMessageScheduled.store(false);
|
||||
WTF::Vector<WTF::String, 12> messages;
|
||||
|
||||
{
|
||||
@@ -365,7 +376,7 @@ public:
|
||||
|
||||
void receiveMessagesOnDebuggerThread(ScriptExecutionContext& context, Zig::GlobalObject* debuggerGlobalObject)
|
||||
{
|
||||
debuggerThreadMessageScheduledCount.store(0);
|
||||
debuggerThreadMessageScheduled.store(false);
|
||||
WTF::Vector<WTF::String, 12> messages;
|
||||
|
||||
{
|
||||
@@ -394,7 +405,7 @@ public:
|
||||
debuggerThreadMessages.append(inputMessage);
|
||||
}
|
||||
|
||||
if (this->debuggerThreadMessageScheduledCount++ == 0) {
|
||||
if (!this->debuggerThreadMessageScheduled.exchange(true)) {
|
||||
debuggerScriptExecutionContext->postTaskConcurrently([connection = this](ScriptExecutionContext& context) {
|
||||
connection->receiveMessagesOnDebuggerThread(context, static_cast<Zig::GlobalObject*>(context.jsGlobalObject()));
|
||||
});
|
||||
@@ -407,10 +418,24 @@ public:
|
||||
Locker<Lock> locker(jsThreadMessagesLock);
|
||||
jsThreadMessages.appendVector(inputMessages);
|
||||
}
|
||||
scheduleInspectorThreadDelivery();
|
||||
}
|
||||
|
||||
void sendMessageToInspectorFromDebuggerThread(const WTF::String& inputMessage)
|
||||
{
|
||||
{
|
||||
Locker<Lock> locker(jsThreadMessagesLock);
|
||||
jsThreadMessages.append(inputMessage);
|
||||
}
|
||||
scheduleInspectorThreadDelivery();
|
||||
}
|
||||
|
||||
private:
|
||||
void scheduleInspectorThreadDelivery()
|
||||
{
|
||||
if (this->jsWaitForMessageFromInspectorLock.isLocked()) {
|
||||
this->jsWaitForMessageFromInspectorLock.unlock();
|
||||
} else if (this->jsThreadMessageScheduledCount++ == 0) {
|
||||
} else if (!this->jsThreadMessageScheduled.exchange(true)) {
|
||||
ScriptExecutionContext::postTaskTo(scriptExecutionContextIdentifier, [connection = this](ScriptExecutionContext& context) {
|
||||
connection->receiveMessagesOnInspectorThread(context, static_cast<Zig::GlobalObject*>(context.jsGlobalObject()), true);
|
||||
});
|
||||
@@ -422,22 +447,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void sendMessageToInspectorFromDebuggerThread(const WTF::String& inputMessage)
|
||||
{
|
||||
{
|
||||
Locker<Lock> locker(jsThreadMessagesLock);
|
||||
jsThreadMessages.append(inputMessage);
|
||||
}
|
||||
|
||||
if (this->jsWaitForMessageFromInspectorLock.isLocked()) {
|
||||
this->jsWaitForMessageFromInspectorLock.unlock();
|
||||
} else if (this->jsThreadMessageScheduledCount++ == 0) {
|
||||
ScriptExecutionContext::postTaskTo(scriptExecutionContextIdentifier, [connection = this](ScriptExecutionContext& context) {
|
||||
connection->receiveMessagesOnInspectorThread(context, static_cast<Zig::GlobalObject*>(context.jsGlobalObject()), true);
|
||||
});
|
||||
this->interruptForMessageDelivery();
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
// Interrupt the JS thread to process pending CDP messages via StopTheWorld.
|
||||
// Only used on the SIGUSR1 runtime activation path where the event loop may
|
||||
@@ -459,11 +469,11 @@ public:
|
||||
|
||||
WTF::Vector<WTF::String, 12> debuggerThreadMessages;
|
||||
WTF::Lock debuggerThreadMessagesLock = WTF::Lock();
|
||||
std::atomic<uint32_t> debuggerThreadMessageScheduledCount { 0 };
|
||||
std::atomic<bool> debuggerThreadMessageScheduled { false };
|
||||
|
||||
WTF::Vector<WTF::String, 12> jsThreadMessages;
|
||||
WTF::Lock jsThreadMessagesLock = WTF::Lock();
|
||||
std::atomic<uint32_t> jsThreadMessageScheduledCount { 0 };
|
||||
std::atomic<bool> jsThreadMessageScheduled { false };
|
||||
|
||||
JSC::JSGlobalObject* globalObject;
|
||||
ScriptExecutionContextIdentifier scriptExecutionContextIdentifier;
|
||||
|
||||
@@ -328,41 +328,19 @@ describe("Runtime inspector activation", () => {
|
||||
});
|
||||
|
||||
test.skipIf(skipASAN)("can interrupt an infinite loop", async () => {
|
||||
using dir = tempDir("debug-infinite-loop-test", {
|
||||
"target.js": `
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// Write PID so parent can find us
|
||||
fs.writeFileSync(path.join(process.cwd(), "pid"), String(process.pid));
|
||||
|
||||
// Infinite loop - the inspector should be able to interrupt this
|
||||
while (true) {}
|
||||
`,
|
||||
});
|
||||
|
||||
// Start target process with infinite loop
|
||||
await using targetProc = spawn({
|
||||
cmd: [bunExe(), "target.js"],
|
||||
cwd: String(dir),
|
||||
cmd: [bunExe(), "-e", `console.log(process.pid); while (true) {}`],
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
// Wait for PID file to be written
|
||||
const pidPath = join(String(dir), "pid");
|
||||
let pid: number | undefined;
|
||||
for (let i = 0; i < 50; i++) {
|
||||
try {
|
||||
const pidText = await Bun.file(pidPath).text();
|
||||
pid = parseInt(pidText, 10);
|
||||
if (pid > 0) break;
|
||||
} catch {
|
||||
// File not ready yet
|
||||
}
|
||||
await Bun.sleep(100);
|
||||
}
|
||||
// Read PID from stdout (written before the infinite loop starts)
|
||||
const reader = targetProc.stdout.getReader();
|
||||
const { value } = await reader.read();
|
||||
reader.releaseLock();
|
||||
const pid = parseInt(new TextDecoder().decode(value).trim(), 10);
|
||||
expect(pid).toBeGreaterThan(0);
|
||||
|
||||
// Use _debugProcess to activate inspector - this should interrupt the infinite loop
|
||||
@@ -389,41 +367,19 @@ describe("Runtime inspector activation", () => {
|
||||
});
|
||||
|
||||
test.skipIf(skipASAN)("can pause execution during while(true) via CDP", async () => {
|
||||
using dir = tempDir("debug-cdp-pause-test", {
|
||||
"target.js": `
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// Write PID so parent can find us
|
||||
fs.writeFileSync(path.join(process.cwd(), "pid"), String(process.pid));
|
||||
|
||||
// Infinite loop - the debugger should be able to pause this via CDP
|
||||
while (true) {}
|
||||
`,
|
||||
});
|
||||
|
||||
// Start target process with infinite loop
|
||||
await using targetProc = spawn({
|
||||
cmd: [bunExe(), "target.js"],
|
||||
cwd: String(dir),
|
||||
cmd: [bunExe(), "-e", `console.log(process.pid); while (true) {}`],
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
// Wait for PID file to be written
|
||||
const pidPath = join(String(dir), "pid");
|
||||
let pid: number | undefined;
|
||||
for (let i = 0; i < 50; i++) {
|
||||
try {
|
||||
const pidText = await Bun.file(pidPath).text();
|
||||
pid = parseInt(pidText, 10);
|
||||
if (pid > 0) break;
|
||||
} catch {
|
||||
// File not ready yet
|
||||
}
|
||||
await Bun.sleep(100);
|
||||
}
|
||||
// Read PID from stdout (written before the infinite loop starts)
|
||||
const reader = targetProc.stdout.getReader();
|
||||
const { value } = await reader.read();
|
||||
reader.releaseLock();
|
||||
const pid = parseInt(new TextDecoder().decode(value).trim(), 10);
|
||||
expect(pid).toBeGreaterThan(0);
|
||||
|
||||
// Activate inspector via _debugProcess
|
||||
|
||||
Reference in New Issue
Block a user