From 58047e7d94e916a83fc995a4917e6e4e9559f6c6 Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Wed, 20 May 2026 08:40:17 -0700 Subject: [PATCH] [vm/native_api] Ensure isolate is not available for duration of native port operations. Follow-up to 5a98fe5564e36d4cffe7918f7c583028457c23ab. TEST=ci Change-Id: I62269b713968f0d0e436d86b7d7b481fc5b52cc5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501620 Commit-Queue: Alexander Aprelev Reviewed-by: Martin Kustermann Reviewed-by: Ryan Macnak --- runtime/vm/isolate.h | 31 +++++++++++++++++++------------ runtime/vm/native_api_impl.cc | 4 ++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index a6ff801986c..7a1ef5971ab 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -1838,27 +1838,34 @@ class EnterIsolateGroupScope { // operate on an individual isolate. class NoActiveIsolateScope : public StackResource { public: - NoActiveIsolateScope() : NoActiveIsolateScope(Thread::Current()) {} - explicit NoActiveIsolateScope(Thread* thread) + explicit NoActiveIsolateScope(bool allow_no_thread = false) + : NoActiveIsolateScope(Thread::Current(), allow_no_thread) {} + explicit NoActiveIsolateScope(Thread* thread, bool allow_no_thread = false) : StackResource(thread), thread_(thread) { - outer_ = thread_->no_active_isolate_scope_; - saved_isolate_ = thread_->isolate_; + ASSERT(allow_no_thread || thread_ != nullptr); + if (thread_ != nullptr) { + outer_ = thread_->no_active_isolate_scope_; + saved_isolate_ = thread_->isolate_; - thread_->no_active_isolate_scope_ = this; - thread_->isolate_ = nullptr; + thread_->no_active_isolate_scope_ = this; + thread_->isolate_ = nullptr; + } } ~NoActiveIsolateScope() { - ASSERT(thread_->isolate_ == nullptr); - thread_->isolate_ = saved_isolate_; - thread_->no_active_isolate_scope_ = outer_; + ASSERT(thread_ == nullptr || thread_->isolate_ == nullptr); + ASSERT(thread_ != nullptr || saved_isolate_ == nullptr); + if (thread_ != nullptr) { + thread_->isolate_ = saved_isolate_; + thread_->no_active_isolate_scope_ = outer_; + } } private: friend class ActiveIsolateScope; - Thread* thread_; - Isolate* saved_isolate_; - NoActiveIsolateScope* outer_; + Thread* thread_ = nullptr; + Isolate* saved_isolate_ = nullptr; + NoActiveIsolateScope* outer_ = nullptr; }; class ActiveIsolateScope : public StackResource { diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc index 57b7ebfa91f..729df6d662f 100644 --- a/runtime/vm/native_api_impl.cc +++ b/runtime/vm/native_api_impl.cc @@ -89,6 +89,7 @@ Dart_NewConcurrentNativePort(const char* name, } ENTER_API_CALL_OR_RETURN(ILLEGAL_PORT); + NoActiveIsolateScope no_active_isolate(/*allow_no_thread=*/true); NativeMessageHandler* nmh = new NativeMessageHandler(name, handler, max_concurrency); Dart_Port port_id = PortMap::CreatePort(nmh); @@ -98,6 +99,7 @@ Dart_NewConcurrentNativePort(const char* name, DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id) { ENTER_API_CALL_OR_RETURN(false) + NoActiveIsolateScope no_active_isolate(/*allow_no_thread=*/true); PortHandler* handler = nullptr; const bool was_closed = PortMap::ClosePort(native_port_id, &handler); if (was_closed) { @@ -122,6 +124,8 @@ DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json, Isolate* isolate = Isolate::Current(); ASSERT(isolate == nullptr || !isolate->is_service_isolate()); + NoActiveIsolateScope no_active_isolate(/*allow_no_thread=*/true); + // We only allow one isolate reload at a time. If this turns out to be on the // critical path, we can change it to have a global datastructure which is // mapping the reply ports to receive buffers.