Skip to content

Commit 76c2573

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm, isolates] Fix deletion of handles when not entered into an isolate group.
Handles may only be allocated/updated/deleted by a thread whose execution state prevents GC from running. TEST=tsan Change-Id: Id2853e30d326642acc572dbd1c03345aaefd0f45 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/398606 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Alexander Aprelev <[email protected]>
1 parent c5b4422 commit 76c2573

File tree

4 files changed

+20
-30
lines changed

4 files changed

+20
-30
lines changed

runtime/lib/isolate.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,6 @@ class IsolateSpawnState {
581581
IsolateGroup* group);
582582
~IsolateSpawnState();
583583

584-
Isolate* isolate() const { return isolate_; }
585-
void set_isolate(Isolate* value) { isolate_ = value; }
586-
587584
Dart_Port parent_port() const { return parent_port_; }
588585
Dart_Port origin_id() const { return origin_id_; }
589586
Dart_Port on_exit_port() const { return on_exit_port_; }
@@ -608,7 +605,6 @@ class IsolateSpawnState {
608605
IsolateGroup* isolate_group() const { return isolate_group_; }
609606

610607
private:
611-
Isolate* isolate_ = nullptr;
612608
Dart_Port parent_port_;
613609
Dart_Port origin_id_ = ILLEGAL_PORT;
614610
Dart_Port on_exit_port_;
@@ -880,12 +876,14 @@ class SpawnIsolateTask : public ThreadPool::Task {
880876
return;
881877
}
882878

883-
state_->set_isolate(child);
884879
if (state_->origin_id() != ILLEGAL_PORT) {
885880
// origin_id is set to parent isolate main port id when spawning via
886881
// spawnFunction.
887882
child->set_origin_id(state_->origin_id());
888883
}
884+
bool errors_are_fatal = state_->errors_are_fatal();
885+
Dart_Port on_error_port = state_->on_error_port();
886+
Dart_Port on_exit_port = state_->on_exit_port();
889887

890888
bool success = true;
891889
{
@@ -895,18 +893,22 @@ class SpawnIsolateTask : public ThreadPool::Task {
895893
HandleScope hs(thread);
896894

897895
success = EnqueueEntrypointInvocationAndNotifySpawner(thread);
896+
897+
// Destruction of [IsolateSpawnState] may cause destruction of [Message]
898+
// which make need to delete persistent handles, so explicitly delete it
899+
// now while we are in the right safepoint state.
900+
state_ = nullptr;
898901
}
899902

900903
if (!success) {
901-
state_ = nullptr;
902904
Dart_ShutdownIsolate();
903905
return;
904906
}
905907

906908
// All preconditions are met for this to always succeed.
907909
char* error = nullptr;
908-
if (!Dart_RunLoopAsync(state_->errors_are_fatal(), state_->on_error_port(),
909-
state_->on_exit_port(), &error)) {
910+
if (!Dart_RunLoopAsync(errors_are_fatal, on_error_port, on_exit_port,
911+
&error)) {
910912
FATAL("Dart_RunLoopAsync() failed: %s. Please file a Dart VM bug report.",
911913
error);
912914
}
@@ -1030,12 +1032,13 @@ class SpawnIsolateTask : public ThreadPool::Task {
10301032
// isolate group).
10311033
if (has_current_isolate) {
10321034
ASSERT(IsolateGroup::Current() == state_->isolate_group());
1035+
TransitionNativeToVM transition(Thread::Current());
10331036
state_ = nullptr;
10341037
} else if (state_->isolate_group() != nullptr) {
10351038
ASSERT(IsolateGroup::Current() == nullptr);
10361039
const bool kBypassSafepoint = false;
10371040
const bool result = Thread::EnterIsolateGroupAsHelper(
1038-
state_->isolate_group(), Thread::kUnknownTask, kBypassSafepoint);
1041+
state_->isolate_group(), Thread::kSpawnTask, kBypassSafepoint);
10391042
ASSERT(result);
10401043
state_ = nullptr;
10411044
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);

runtime/vm/dart_api_state.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,13 @@ class PersistentHandle {
178178
ptr_ = static_cast<ObjectPtr>(reinterpret_cast<uword>(free_list));
179179
ASSERT(!ptr_->IsHeapObject());
180180
}
181-
void FreeHandle(PersistentHandle* free_list) { SetNext(free_list); }
181+
void FreeHandle(PersistentHandle* free_list) {
182+
#if defined(DEBUG)
183+
Thread* thread = Thread::Current();
184+
ASSERT(thread->MayAllocateHandles());
185+
#endif // DEBUG
186+
SetNext(free_list);
187+
}
182188

183189
ObjectPtr ptr_;
184190
DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.

runtime/vm/thread.cc

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -253,24 +253,6 @@ ErrorPtr Thread::StealStickyError() {
253253
return return_value;
254254
}
255255

256-
const char* Thread::TaskKindToCString(TaskKind kind) {
257-
switch (kind) {
258-
case kUnknownTask:
259-
return "kUnknownTask";
260-
case kMutatorTask:
261-
return "kMutatorTask";
262-
case kCompilerTask:
263-
return "kCompilerTask";
264-
case kSweeperTask:
265-
return "kSweeperTask";
266-
case kMarkerTask:
267-
return "kMarkerTask";
268-
default:
269-
UNREACHABLE();
270-
return "";
271-
}
272-
}
273-
274256
void Thread::AssertNonMutatorInvariants() {
275257
ASSERT(BypassSafepoints());
276258
ASSERT(store_buffer_block_ == nullptr);

runtime/vm/thread.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,8 @@ class Thread : public ThreadState {
365365
kScavengerTask,
366366
kSampleBlockTask,
367367
kIncrementalCompactorTask,
368+
kSpawnTask,
368369
};
369-
// Converts a TaskKind to its corresponding C-String name.
370-
static const char* TaskKindToCString(TaskKind kind);
371370

372371
~Thread();
373372

0 commit comments

Comments
 (0)