Avoid leaking Promises when detaching debugger
When the debugger is active and a Promise begins executing, Isolate::PushPromise adds a global handle for that Promise. If the debugger is no longer attached when the Promise finishes executing, then there is no corresponding call to PopPromise which would clean up the global handle. To avoid leaking memory in that case, we should clean up the Promise stack when detaching the debugger. Bug: v8:12613 Change-Id: I47a2c37713b43b482e23e2457e96fba5f52623f4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3448949 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Cr-Commit-Position: refs/heads/main@{#79017}
This commit is contained in:
parent
0d05f1807d
commit
aae45ca822
@ -440,6 +440,7 @@ void Debug::Unload() {
|
||||
ClearStepping();
|
||||
RemoveAllCoverageInfos();
|
||||
ClearAllDebuggerHints();
|
||||
ClearGlobalPromiseStack();
|
||||
debug_delegate_ = nullptr;
|
||||
}
|
||||
|
||||
@ -1990,6 +1991,11 @@ void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev,
|
||||
delete node;
|
||||
}
|
||||
|
||||
void Debug::ClearGlobalPromiseStack() {
|
||||
while (isolate_->PopPromise()) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
|
||||
RCS_SCOPE(isolate_, RuntimeCallCounterId::kDebugger);
|
||||
HandleScope scope(isolate_);
|
||||
|
@ -475,6 +475,8 @@ class V8_EXPORT_PRIVATE Debug {
|
||||
DebugInfoListNode** curr);
|
||||
void FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node);
|
||||
|
||||
void ClearGlobalPromiseStack();
|
||||
|
||||
void SetTemporaryObjectTrackingDisabled(bool disabled);
|
||||
bool GetTemporaryObjectTrackingDisabled() const;
|
||||
|
||||
|
@ -2599,14 +2599,15 @@ void Isolate::PushPromise(Handle<JSObject> promise) {
|
||||
tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev);
|
||||
}
|
||||
|
||||
void Isolate::PopPromise() {
|
||||
bool Isolate::PopPromise() {
|
||||
ThreadLocalTop* tltop = thread_local_top();
|
||||
if (tltop->promise_on_stack_ == nullptr) return;
|
||||
if (tltop->promise_on_stack_ == nullptr) return false;
|
||||
PromiseOnStack* prev = tltop->promise_on_stack_->prev();
|
||||
Handle<Object> global_promise = tltop->promise_on_stack_->promise();
|
||||
delete tltop->promise_on_stack_;
|
||||
tltop->promise_on_stack_ = prev;
|
||||
global_handles()->Destroy(global_promise.location());
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -855,7 +855,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
|
||||
// Push and pop a promise and the current try-catch handler.
|
||||
void PushPromise(Handle<JSObject> promise);
|
||||
void PopPromise();
|
||||
bool PopPromise();
|
||||
|
||||
// Return the relevant Promise that a throw/rejection pertains to, based
|
||||
// on the contents of the Promise stack
|
||||
|
Loading…
Reference in New Issue
Block a user