Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions NativeScript/runtime/ArgConverter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@

{
v8::Locker locker(isolate);
// Checked again with the isolate locked: a runtime being destroyed holds
// this lock while it removes its caches, so the check above can pass and
// the lock then be granted only once the context is gone. ~Runtime drops
// the isolate from the live registry before it takes the lock, which is
// what makes this second look reliable.
if (!data->isolateWrapper_.IsValid()) {
memset(retValue, 0, cif->rtype->size);
return;
}
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
std::shared_ptr<Caches> cache = Caches::Get(isolate);
Expand Down
32 changes: 18 additions & 14 deletions NativeScript/runtime/Interop.mm
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,26 @@
if (wrapper->isolateWrapper_.IsValid()) {
Isolate* isolate = wrapper->isolateWrapper_.Isolate();
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Value> callback = wrapper->callback_->Get(isolate);
if (!callback.IsEmpty() && callback->IsObject()) {
// The callback's slot is the cache's owner, so only a wrapper
// still sitting in it is ours to free.
if (tns::GetValue(isolate, callback) == blockWrapper) {
tns::DeleteValue(isolate, callback);
} else {
blockWrapper = nullptr;
// Re-checked under the lock: ~Runtime holds it while it tears the
// isolate's caches down, so the check above can predate that.
if (wrapper->isolateWrapper_.IsValid()) {
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Value> callback = wrapper->callback_->Get(isolate);
if (!callback.IsEmpty() && callback->IsObject()) {
// The callback's slot is the cache's owner, so only a wrapper
// still sitting in it is ours to free.
if (tns::GetValue(isolate, callback) == blockWrapper) {
tns::DeleteValue(isolate, callback);
} else {
blockWrapper = nullptr;
}
}
// Unconditional: an already-detached callback still owns its
// node, and dropping the persistent without a reset would leave
// that node rooted forever.
wrapper->callback_->Reset();
}
// Unconditional: an already-detached callback still owns its
// node, and dropping the persistent without a reset would leave
// that node rooted forever.
wrapper->callback_->Reset();
}
// Outside the isolate guard: once the isolate is gone the cache
// slot is unreachable and nothing else can free the wrapper.
Expand Down