[vm] Fix deadlock in isolate shutdown, take 2.

Enter a safepoint when waiting for child isolate spawns to complete, since the child isolate now requires its parent (along with all other members of the isolate group) to participate in safepoints.

Adjust shutdown of ThreadPool isolates to re-enter the isolate before waiting for outstanding spawns.

Bug: https://github.com/dart-lang/sdk/issues/37679
Change-Id: I760c0f75b77a3884ac3f4757f0c6920a417f3453
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111524
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Ryan Macnak 2019-08-01 19:04:11 +00:00
parent 6cec64691b
commit b66cd42372
4 changed files with 10 additions and 10 deletions

View file

@ -1808,15 +1808,17 @@ static MessageHandler::MessageStatus RunIsolate(uword parameter) {
static void ShutdownIsolate(uword parameter) {
Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
// We must wait for any outstanding spawn calls to complete before
// running the shutdown callback.
isolate->WaitForOutstandingSpawns();
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
StartIsolateScope start_scope(isolate);
Thread* thread = Thread::Current();
ASSERT(thread->isolate() == isolate);
// We must wait for any outstanding spawn calls to complete before
// running the shutdown callback.
isolate->WaitForOutstandingSpawns();
StackZone zone(thread);
HandleScope handle_scope(thread);
#if defined(DEBUG)
@ -2998,9 +3000,11 @@ void Isolate::DecrementSpawnCount() {
}
void Isolate::WaitForOutstandingSpawns() {
Thread* thread = Thread::Current();
ASSERT(thread != NULL);
MonitorLocker ml(&spawn_count_monitor_);
while (spawn_count_ > 0) {
ml.Wait();
ml.WaitWithSafepointCheck(thread);
}
}

View file

@ -134,7 +134,6 @@ class RunKernelTask : public ThreadPool::Task {
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n");
}
Isolate* I = reinterpret_cast<Isolate*>(parameter);
I->WaitForOutstandingSpawns();
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
@ -142,6 +141,7 @@ class RunKernelTask : public ThreadPool::Task {
StartIsolateScope start_scope(I);
Thread* T = Thread::Current();
ASSERT(I == T->isolate());
I->WaitForOutstandingSpawns();
StackZone zone(T);
HandleScope handle_scope(T);
Error& error = Error::Handle(Z);

View file

@ -381,7 +381,6 @@ class RunServiceTask : public ThreadPool::Task {
}
Isolate* I = reinterpret_cast<Isolate*>(parameter);
ASSERT(ServiceIsolate::IsServiceIsolate(I));
I->WaitForOutstandingSpawns();
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
@ -389,6 +388,7 @@ class RunServiceTask : public ThreadPool::Task {
StartIsolateScope start_scope(I);
Thread* T = Thread::Current();
ASSERT(I == T->isolate());
I->WaitForOutstandingSpawns();
StackZone zone(T);
HandleScope handle_scope(T);
Error& error = Error::Handle(Z);

View file

@ -9,10 +9,6 @@ LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
LibTest/isolate/Isolate/kill_A01_t01: Skip # Issue 37699
LibTest/isolate/Isolate/pause_A01_t01: Skip # Issue 37699
LibTest/isolate/Isolate/pause_A01_t02: Skip # Issue 37699
LibTest/isolate/ReceivePort/firstWhere_A01_t01: Skip # Issue 37679
LibTest/isolate/ReceivePort/firstWhere_A02_t01: Skip # Issue 37679
LibTest/isolate/ReceivePort/transform_A01_t01: Skip # Issue 37679
LibTest/isolate/ReceivePort/transform_A01_t02: Skip # Issue 37679
[ $compiler == dartkp ]
Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError