[vm, profiler] Don't assume the isolate has a mutator during a profile sample.

A sample can be taken when Thread::Current() and Thread::Current()->isolate() are non-NULL. When a thread is entering or exiting an isolate, the is a brief window between the TLS being set/cleared and Isolate::mutator_thread_ being set/cleared.

TEST=vm/cc/Profiler_EnterExitIsolate
Bug: https://github.com/flutter/flutter/issues/134548
Change-Id: I7a6b25dabf930e8480d1a85d7f24c4765fc36b15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/328380
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ryan Macnak 2023-10-02 17:57:33 +00:00 committed by Commit Queue
parent ebd669a0d4
commit f36c109471
2 changed files with 24 additions and 3 deletions

View file

@ -820,9 +820,13 @@ Sample* SampleBlockBuffer::ReserveSampleImpl(Isolate* isolate,
}
if (block != nullptr) {
block->MarkCompleted();
if (!Isolate::IsSystemIsolate(isolate) &&
isolate->TrySetHasCompletedBlocks()) {
isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
if (!Isolate::IsSystemIsolate(isolate)) {
Thread* mutator = isolate->mutator_thread();
// The mutator thread might be NULL if we sample in the middle of
// Thread::Enter/ExitIsolate.
if ((mutator != nullptr) && isolate->TrySetHasCompletedBlocks()) {
mutator->ScheduleInterrupts(Thread::kVMInterrupt);
}
}
}
return next->ReserveSample();

View file

@ -2430,6 +2430,23 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ProfileCodeTableTest) {
EXPECT_EQ(table->FindCodeForPC(50), code1);
}
// Try to hit any races in related to setting TLS and Isolate::mutator_thread_.
// https://github.com/flutter/flutter/issues/134548
ISOLATE_UNIT_TEST_CASE(Profiler_EnterExitIsolate) {
EnableProfiler();
Profiler::SetSamplePeriod(50); // Microseconds.
const char* kScript = "main() => null;\n";
const Library& root_library = Library::Handle(LoadTestScript(kScript));
Isolate* isolate = Isolate::Current();
for (intptr_t i = 0; i < 100000; i++) {
Thread::ExitIsolate();
Thread::EnterIsolate(isolate);
Invoke(root_library, "main");
}
}
#endif // !PRODUCT
} // namespace dart