Skip to content

Commit 3feb138

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm] Fix race calling Dart_CloseNativePort during/after Dart_Cleanup.
Fix race between service/kernel isolate startup and Dart_Init. TEST=DartAPI_InvokeVMServiceMethod[_Loop] under rr chaos mode Bug: #57096 Change-Id: I50a26d61efa9106ce4bff0b268e68088570f97d0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/397984 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Slava Egorov <[email protected]>
1 parent dcb9ec1 commit 3feb138

File tree

2 files changed

+44
-30
lines changed

2 files changed

+44
-30
lines changed

runtime/vm/dart.cc

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -501,27 +501,6 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
501501
Isolate::SetRegisterKernelBlobCallback(params->register_kernel_blob);
502502
Isolate::SetUnregisterKernelBlobCallback(params->unregister_kernel_blob);
503503

504-
#ifndef PRODUCT
505-
const bool support_service = true;
506-
Service::SetGetServiceAssetsCallback(params->get_service_assets);
507-
#else
508-
const bool support_service = false;
509-
#endif
510-
511-
const bool is_dart2_aot_precompiler =
512-
FLAG_precompiled_mode && !kDartPrecompiledRuntime;
513-
514-
if (!is_dart2_aot_precompiler &&
515-
(support_service || !kDartPrecompiledRuntime)) {
516-
ServiceIsolate::Run();
517-
}
518-
519-
#ifndef DART_PRECOMPILED_RUNTIME
520-
if (params->start_kernel_isolate) {
521-
KernelIsolate::InitializeState();
522-
}
523-
#endif // DART_PRECOMPILED_RUNTIME
524-
525504
return nullptr;
526505
}
527506

@@ -538,6 +517,21 @@ char* Dart::Init(const Dart_InitializeParams* params) {
538517
return retval;
539518
}
540519
DartInitializationState::SetInitialized();
520+
521+
// The service and kernel isolates require the VM state to be initialized.
522+
// The embedder, not the VM, should trigger creation of the service and kernel
523+
// isolates. https://github.com/dart-lang/sdk/issues/33433
524+
#if !defined(PRODUCT)
525+
Service::SetGetServiceAssetsCallback(params->get_service_assets);
526+
ServiceIsolate::Run();
527+
#endif
528+
529+
#if !defined(DART_PRECOMPILED_RUNTIME)
530+
if (params->start_kernel_isolate) {
531+
KernelIsolate::InitializeState();
532+
}
533+
#endif
534+
541535
return nullptr;
542536
}
543537

runtime/vm/native_api_impl.cc

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@ class IsolateLeaveScope {
4343
DISALLOW_COPY_AND_ASSIGN(IsolateLeaveScope);
4444
};
4545

46+
class DartApiCallScope : public ValueObject {
47+
public:
48+
DartApiCallScope() : active_(Dart::SetActiveApiCall()) {}
49+
~DartApiCallScope() {
50+
if (active_) {
51+
Dart::ResetActiveApiCall();
52+
}
53+
}
54+
bool active() const { return active_; }
55+
56+
private:
57+
const bool active_;
58+
};
59+
60+
#define ENTER_API_CALL_OR_RETURN(failure_value) \
61+
DartApiCallScope api_call_scope; \
62+
if (!api_call_scope.active()) { \
63+
return failure_value; \
64+
}
65+
4666
static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
4767
AllocOnlyStackZone zone;
4868
std::unique_ptr<Message> msg = WriteApiMessage(
@@ -89,20 +109,19 @@ Dart_NewConcurrentNativePort(const char* name,
89109
CURRENT_FUNC);
90110
return ILLEGAL_PORT;
91111
}
92-
if (!Dart::SetActiveApiCall()) {
93-
return ILLEGAL_PORT;
94-
}
112+
ENTER_API_CALL_OR_RETURN(ILLEGAL_PORT);
95113
// Start the native port without a current isolate.
96114
IsolateLeaveScope saver(Isolate::Current());
97115

98116
NativeMessageHandler* nmh =
99117
new NativeMessageHandler(name, handler, max_concurrency);
100118
Dart_Port port_id = PortMap::CreatePort(nmh);
101-
Dart::ResetActiveApiCall();
102119
return port_id;
103120
}
104121

105122
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id) {
123+
ENTER_API_CALL_OR_RETURN(false)
124+
106125
// Close the native port without a current isolate.
107126
IsolateLeaveScope saver(Isolate::Current());
108127

@@ -121,15 +140,16 @@ DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json,
121140
intptr_t* response_json_length,
122141
char** error) {
123142
#if !defined(PRODUCT)
124-
Isolate* isolate = Isolate::Current();
125-
ASSERT(isolate == nullptr || !isolate->is_service_isolate());
126-
IsolateLeaveScope saver(isolate);
127-
128-
if (!Dart::IsInitialized()) {
143+
DartApiCallScope api_call;
144+
if (!api_call.active()) {
129145
*error = ::dart::Utils::StrDup("VM Service is not active.");
130146
return false;
131147
}
132148

149+
Isolate* isolate = Isolate::Current();
150+
ASSERT(isolate == nullptr || !isolate->is_service_isolate());
151+
IsolateLeaveScope saver(isolate);
152+
133153
// We only allow one isolate reload at a time. If this turns out to be on the
134154
// critical path, we can change it to have a global datastructure which is
135155
// mapping the reply ports to receive buffers.

0 commit comments

Comments
 (0)