@@ -771,28 +771,49 @@ void Worker::TakeHeapSnapshot(const FunctionCallbackInfo<Value>& args) {
771
771
->NewInstance (env->context ()).ToLocal (&wrap)) {
772
772
return ;
773
773
}
774
- BaseObjectPtr<WorkerHeapSnapshotTaker> taker =
775
- MakeDetachedBaseObject<WorkerHeapSnapshotTaker>(env, wrap);
774
+
775
+ // The created WorkerHeapSnapshotTaker is an object owned by main
776
+ // thread's Isolate, it can not be accessed by worker thread
777
+ std::unique_ptr<BaseObjectPtr<WorkerHeapSnapshotTaker>> taker =
778
+ std::make_unique<BaseObjectPtr<WorkerHeapSnapshotTaker>>(
779
+ MakeDetachedBaseObject<WorkerHeapSnapshotTaker>(env, wrap));
776
780
777
781
// Interrupt the worker thread and take a snapshot, then schedule a call
778
782
// on the parent thread that turns that snapshot into a readable stream.
779
- bool scheduled = w->RequestInterrupt ([taker, env](Environment* worker_env) {
780
- heap::HeapSnapshotPointer snapshot {
781
- worker_env->isolate ()->GetHeapProfiler ()->TakeHeapSnapshot () };
783
+ bool scheduled = w->RequestInterrupt ([taker = std::move (taker),
784
+ env](Environment* worker_env) mutable {
785
+ heap::HeapSnapshotPointer snapshot{
786
+ worker_env->isolate ()->GetHeapProfiler ()->TakeHeapSnapshot ()};
782
787
CHECK (snapshot);
788
+
789
+ // Here, the worker thread temporarily owns the WorkerHeapSnapshotTaker
790
+ // object.
791
+
783
792
env->SetImmediateThreadsafe (
784
- [taker, snapshot = std::move (snapshot)](Environment* env) mutable {
793
+ [taker = std::move (taker),
794
+ snapshot = std::move (snapshot)](Environment* env) mutable {
785
795
HandleScope handle_scope (env->isolate ());
786
796
Context::Scope context_scope (env->context ());
787
797
788
- AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (taker.get ());
789
- BaseObjectPtr<AsyncWrap> stream = heap::CreateHeapSnapshotStream (
790
- env, std::move (snapshot));
791
- Local<Value> args[] = { stream->object () };
792
- taker->MakeCallback (env->ondone_string (), arraysize (args), args);
793
- }, CallbackFlags::kUnrefed );
798
+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (taker->get ());
799
+ BaseObjectPtr<AsyncWrap> stream =
800
+ heap::CreateHeapSnapshotStream (env, std::move (snapshot));
801
+ Local<Value> args[] = {stream->object ()};
802
+ taker->get ()->MakeCallback (
803
+ env->ondone_string (), arraysize (args), args);
804
+ // implicitly delete `taker`
805
+ },
806
+ CallbackFlags::kUnrefed );
807
+
808
+ // Now, the lambda is delivered to the main thread, as a result, the
809
+ // WorkerHeapSnapshotTaker object is delivered to the main thread, too.
794
810
});
795
- args.GetReturnValue ().Set (scheduled ? taker->object () : Local<Object>());
811
+
812
+ if (scheduled) {
813
+ args.GetReturnValue ().Set (wrap);
814
+ } else {
815
+ args.GetReturnValue ().Set (Local<Object>());
816
+ }
796
817
}
797
818
798
819
void Worker::LoopIdleTime (const FunctionCallbackInfo<Value>& args) {
0 commit comments