fix: crash in gin::wrappable::secondweakcallback (#45378)

fix: crash in gin::wrappable::secondweakcallback (#45368)
This commit is contained in:
Keeley Hammond 2025-01-29 15:04:08 -08:00 committed by GitHub
parent e99328a45e
commit ef1ad85082
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 230 additions and 3 deletions

View file

@ -236,6 +236,10 @@ const char* Notification::GetTypeName() {
return GetClassName();
}
void Notification::WillBeDestroyed() {
ClearWeak();
}
} // namespace electron::api
namespace {

View file

@ -57,6 +57,9 @@ class Notification final : public gin::Wrappable<Notification>,
static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
// disable copy
Notification(const Notification&) = delete;
Notification& operator=(const Notification&) = delete;

View file

@ -1852,6 +1852,10 @@ const char* Session::GetTypeName() {
return GetClassName();
}
void Session::WillBeDestroyed() {
ClearWeak();
}
} // namespace electron::api
namespace {

View file

@ -102,6 +102,9 @@ class Session final : public gin::Wrappable<Session>,
static const char* GetClassName() { return "Session"; }
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
// Methods.
v8::Local<v8::Promise> ResolveHost(
std::string host,

View file

@ -431,6 +431,10 @@ const char* Tray::GetTypeName() {
return GetClassName();
}
void Tray::WillBeDestroyed() {
ClearWeak();
}
} // namespace electron::api
namespace {

View file

@ -58,6 +58,9 @@ class Tray final : public gin::Wrappable<Tray>,
static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
// disable copy
Tray(const Tray&) = delete;
Tray& operator=(const Tray&) = delete;

View file

@ -4570,6 +4570,10 @@ const char* WebContents::GetTypeName() {
return GetClassName();
}
void WebContents::WillBeDestroyed() {
ClearWeak();
}
ElectronBrowserContext* WebContents::GetBrowserContext() const {
return static_cast<ElectronBrowserContext*>(
web_contents()->GetBrowserContext());

View file

@ -179,6 +179,9 @@ class WebContents final : public ExclusiveAccessContext,
static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
void Destroy();
void Close(std::optional<gin_helper::Dictionary> options);
base::WeakPtr<WebContents> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }

View file

@ -306,6 +306,10 @@ const char* MessagePort::GetTypeName() {
return "MessagePort";
}
void MessagePort::WillBeDestroyed() {
ClearWeak();
}
} // namespace electron
namespace {

View file

@ -61,6 +61,9 @@ class MessagePort final : public gin::Wrappable<MessagePort>,
v8::Isolate* isolate) override;
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
private:
MessagePort();

View file

@ -132,11 +132,16 @@ v8::Isolate* JavascriptEnvironment::GetIsolate() {
void JavascriptEnvironment::CreateMicrotasksRunner() {
DCHECK(!microtasks_runner_);
microtasks_runner_ = std::make_unique<MicrotasksRunner>(isolate());
isolate_holder_.WillCreateMicrotasksRunner();
base::CurrentThread::Get()->AddTaskObserver(microtasks_runner_.get());
}
void JavascriptEnvironment::DestroyMicrotasksRunner() {
DCHECK(microtasks_runner_);
// Should be called before running gin_helper::CleanedUpAtExit::DoCleanup.
// This helps to signal wrappable finalizer callbacks to not act on freed
// parameters.
isolate_holder_.WillDestroyMicrotasksRunner();
{
v8::HandleScope scope(isolate_);
gin_helper::CleanedUpAtExit::DoCleanup();

View file

@ -819,4 +819,8 @@ const char* SimpleURLLoaderWrapper::GetTypeName() {
return "SimpleURLLoaderWrapper";
}
void SimpleURLLoaderWrapper::WillBeDestroyed() {
ClearWeak();
}
} // namespace electron::api

View file

@ -66,6 +66,9 @@ class SimpleURLLoaderWrapper final
v8::Isolate* isolate) override;
const char* GetTypeName() override;
// gin_helper::CleanedUpAtExit
void WillBeDestroyed() override;
private:
SimpleURLLoaderWrapper(ElectronBrowserContext* browser_context,
std::unique_ptr<network::ResourceRequest> request,

View file

@ -27,11 +27,14 @@ CleanedUpAtExit::~CleanedUpAtExit() {
std::erase(GetDoomed(), this);
}
void CleanedUpAtExit::WillBeDestroyed() {}
// static
void CleanedUpAtExit::DoCleanup() {
auto& doomed = GetDoomed();
while (!doomed.empty()) {
CleanedUpAtExit* next = doomed.back();
next->WillBeDestroyed();
delete next;
}
}

View file

@ -19,6 +19,8 @@ class CleanedUpAtExit {
CleanedUpAtExit();
virtual ~CleanedUpAtExit();
virtual void WillBeDestroyed();
static void DoCleanup();
};

View file

@ -4,6 +4,7 @@
#include "shell/common/gin_helper/wrappable.h"
#include "gin/public/isolate_holder.h"
#include "shell/common/gin_helper/dictionary.h"
#include "v8/include/v8-function.h"
@ -60,8 +61,10 @@ void WrappableBase::InitWith(v8::Isolate* isolate,
// static
void WrappableBase::FirstWeakCallback(
const v8::WeakCallbackInfo<WrappableBase>& data) {
auto* wrappable = static_cast<WrappableBase*>(data.GetInternalField(0));
if (wrappable) {
WrappableBase* wrappable = data.GetParameter();
auto* wrappable_from_field =
static_cast<WrappableBase*>(data.GetInternalField(0));
if (wrappable && wrappable == wrappable_from_field) {
wrappable->wrapper_.Reset();
data.SetSecondPassCallback(SecondWeakCallback);
}
@ -70,6 +73,9 @@ void WrappableBase::FirstWeakCallback(
// static
void WrappableBase::SecondWeakCallback(
const v8::WeakCallbackInfo<WrappableBase>& data) {
if (gin::IsolateHolder::DestroyedMicrotasksRunner()) {
return;
}
delete static_cast<WrappableBase*>(data.GetInternalField(0));
}