mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 05:42:43 +00:00
fix: safely write usePollingTraps by temporarily unprotecting frozen JSC config page
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
#include "BunInjectedScriptHost.h"
|
||||
#include <JavaScriptCore/JSGlobalObjectInspectorController.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <JavaScriptCore/JSCConfig.h>
|
||||
#include "InspectorLifecycleAgent.h"
|
||||
#include "InspectorTestReporterAgent.h"
|
||||
#include "InspectorBunFrontendDevServerAgent.h"
|
||||
@@ -1003,10 +1006,27 @@ extern "C" void VM__cancelStop(JSC::VM* vm)
|
||||
vm->cancelStop();
|
||||
}
|
||||
|
||||
// Called from Zig when the event loop path activates the inspector.
|
||||
// Ensures runtimeInspectorActivated is set so that connect() and
|
||||
// Called from Zig and from the STW callback when the inspector activates.
|
||||
// Sets runtimeInspectorActivated so that connect() and
|
||||
// interruptForMessageDelivery() use STW-based message delivery.
|
||||
// Also enables usePollingTraps for 100% reliable trap delivery in DFG/FTL.
|
||||
// Since JSC::Options are mprotected read-only after init, we temporarily
|
||||
// unprotect the config page, write, and re-protect.
|
||||
extern "C" void Bun__activateRuntimeInspectorMode()
|
||||
{
|
||||
Bun::runtimeInspectorActivated.store(true);
|
||||
|
||||
// Enable polling traps so NeedDebuggerBreak is checked at every loop
|
||||
// back-edge in DFG/FTL code. Without this, while(true){} can only be
|
||||
// interrupted by signal-based traps (~94% reliable per attempt).
|
||||
auto& options = g_jscConfig.options;
|
||||
if (!options.usePollingTraps) {
|
||||
// The config page is frozen (mprotect PROT_READ). Temporarily make it writable.
|
||||
size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||
void* pageBase = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&options) & ~(pageSize - 1));
|
||||
size_t protectSize = (reinterpret_cast<uintptr_t>(&options) + sizeof(options) - reinterpret_cast<uintptr_t>(pageBase) + pageSize - 1) & ~(pageSize - 1);
|
||||
mprotect(pageBase, protectSize, PROT_READ | PROT_WRITE);
|
||||
options.usePollingTraps = true;
|
||||
mprotect(pageBase, protectSize, PROT_READ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +314,8 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c
|
||||
// The tradeoff: signal-based trap delivery for requestStopAll (used by the
|
||||
// runtime inspector via SIGUSR1) is ~94% reliable vs 100% with polling.
|
||||
// We accept this for the inspector path since speed is the priority.
|
||||
// IMPORTANT: JSC::Options are frozen (mprotected read-only) after init.
|
||||
// Writing to usePollingTraps later crashes on Linux with SEGV at offset 0xB34.
|
||||
JSC::Options::evalMode() = evalMode;
|
||||
JSC::Options::heapGrowthSteepnessFactor() = 1.0;
|
||||
JSC::Options::heapGrowthMaxIncrease() = 2.0;
|
||||
|
||||
Reference in New Issue
Block a user