forked from WebKit/WebKit
-
Notifications
You must be signed in to change notification settings - Fork 52
InspectorDebuggerAgent: make Debugger.disable idempotent #385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
robobun
wants to merge
1
commit into
main
Choose a base branch
from
farm/de685579/debugger-disable-idempotent
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟣 Not introduced by this PR, but noting since it lives in the exact teardown path being gated here (
disable()→internalDisable()→clearInspectorBreakpointState()): thereplacedInternalFunctions()cleanup lambda at ~line 2160 checks== &m_debugger.vm()where the three parallel sites (both lambdas inremoveSymbolicBreakpoint()and thereplacedThunks()lambda immediately above) all use!=. The inversion means this VM's ownInternalFunctiondebugger hooks are never uninstalled on disable, and in a multi-VM process it decrementsmatchCounton other VMs' entries instead. Pre-existing (from 0424321); feel free to leave for a follow-up.Extended reasoning...
What the bug is
In
InspectorDebuggerAgent::clearInspectorBreakpointState()— whichinternalDisable()calls, and whose entry point (disable()) this PR now guards — thereplacedInternalFunctions()cleanup lambda has an inverted VM-ownership check:Compare with the three parallel sites, all of which use
!=:removeSymbolicBreakpoint(),replacedThunks()lambda:!= &m_debugger.vm()removeSymbolicBreakpoint(),replacedInternalFunctions()lambda:!= &m_debugger.vm()clearInspectorBreakpointState(),replacedThunks()lambda (immediately above):!= &m_debugger.vm()clearInspectorBreakpointState(),replacedInternalFunctions()lambda:== &m_debugger.vm()← invertedCode path
replacedInternalFunctions()is a process-globalVector<Box<ReplacedInternalFunction>>shared across all VMs. Each entry records anInternalFunctionwhose native call/construct pointers were swapped forinternalFunctionCallWithDebuggerHook/internalFunctionConstructWithDebuggerHook. The intendedremoveAllMatchingpattern is:true).false).matchCountper matching symbolic breakpoint; remove when it reaches zero.With
==, step 2 fires for this VM's entries — they are unconditionally kept — and step 3 runs against other VMs' entries.Why nothing else prevents it
The only other removal path is
removeSymbolicBreakpoint(), which is per-breakpoint.clearInspectorBreakpointState()is the bulk-teardown path used onDebugger.disable/ frontend disconnect, and it is the only place that clearsm_symbolicBreakpointswholesale. Since~ReplacedInternalFunction()is what restores the original native function pointers, keeping theBoxalive means the hook is never uninstalled.Impact
Debugger.disable, everyReplacedInternalFunctionentry for this VM is kept. The hookedInternalFunctions continue callinginternalFunctionWithDebuggerHookafter the debugger is disabled, and the entries leak in the process-global vector across enable/disable cycles.matchCountdecremented (and possibly removed) using this agent'sm_symbolicBreakpoints, which can prematurely uninstall another VM's hooks.Step-by-step proof
Debugger.enable, thenDebugger.addSymbolicBreakpointmatching e.g.Array.didCreateInternalFunction()swaps the native pointer and appends aBox<ReplacedInternalFunction>withmatchCount = 1to the global vector.Debugger.disable→internalDisable(false)→clearInspectorBreakpointState().replacedInternalFunctions().removeAllMatchinglambda: the weak ref is live, and&internalFunction->vm() == &m_debugger.vm()is true →return false(keep).matchCountis never decremented;~ReplacedInternalFunction()never runs; the hook stays installed.m_symbolicBreakpoints.clear()runs afterward, so a subsequent enable starts with an empty breakpoint list but a non-empty globalreplacedInternalFunctions()— the entry is now orphaned.Fix
Change
==to!=at line ~2160 to match the other three sites.Provenance
git blameattributes line 2160 to0424321c96(2026-07-16 upstream merge), predating this PR. The PR only adds theif (!enabled()) return { };guard and does not touch this code, so this is pre-existing — flagged only because it sits directly in the teardown path whose entry point the PR is modifying.