Странное поведение от использования V8 v8::EmbedderHeapTracer
Я испытываю трудности с использованием v8::EmbedderHeapTracer
API с версией V8 6.3.
Моя проблема заключается в следующей последовательности событий, происходящих в следующем порядке:
- V8 позвонит
TracePrologue
, - V8 зарегистрирует ссылку V8 для поля внедрения
pointer
сRegisterV8References
, - Необязательно: я пробовал как звонить, так и не звонить
RegisterExternalReference
на объекте поле для вставки хранится здесь. Интуитивно, я ожидал бы, что это будет избыточной информацией, поскольку V8 уже обнаружил, что это достижимо, но я попытался назвать это из паранойи. - Я добавлю
pointer
к моей границе (например, стек для обхода DFS кучи устройства для внедрения). - V8 будет затем запустить
SetWeak
обратный звонок наv8::Persistent<v8::Object>
что это только что зарегистрировано раньше. Это заставит меня удалить объект. - Обратите внимание, что ни
EnterFinalPause
ниTraceEpilogue
были вызваны еще. pointer
удаляется от границы, и я пытаюсь расширить его. Это приводит к использованию кучи после освобождения (определяется ASan).
Должны ли я беспокоиться о том, что объекты, которые определены как достижимые при удалении в одном и том же цикле GC? Я бы подумал, что все, что имеет RegisterExternalReference
призвал его будет оставаться в живых, по крайней мере, до следующего цикла GC.
Дополнительная информация:
ASan dump:
=================================================================
==184290==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c0001687c0 at pc 0x0000053ad97e bp 0x7f36d0676f30 sp 0x7f36d0676f28
READ of size 8 at 0x60c0001687c0 thread T30 (MainWebModule)
#0 0x53ad97d in cobalt::script::v8c::V8cHeapTracer::AdvanceTracing(double, v8::EmbedderHeapTracer::AdvanceTracingActions) out/linux-x64x11-v8_debug/../../cobalt/script/v8c/v8c_heap_tracer.cc:76:16
#1 0x675d8e2 in v8::internal::LocalEmbedderHeapTracer::Trace(double, v8::EmbedderHeapTracer::AdvanceTracingActions) out/linux-x64x11-v8_debug/../../v8/src/heap/embedder-tracing.cc:45:26
#2 0x67975e7 in v8::internal::MarkCompactCollector::ProcessEphemeralMarking(bool) out/linux-x64x11-v8_debug/../../v8/src/heap/mark-compact.cc:1847:46
#3 0x678ed88 in v8::internal::MarkCompactCollector::MarkLiveObjects() out/linux-x64x11-v8_debug/../../v8/src/heap/mark-compact.cc:2558:7
#4 0x678d983 in v8::internal::MarkCompactCollector::CollectGarbage() out/linux-x64x11-v8_debug/../../v8/src/heap/mark-compact.cc:525:3
#5 0x66ab63d in v8::internal::Heap::MarkCompact() out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1684:29
#6 0x66a835f in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1557:9
#7 0x66a6c48 in v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1216:11
#8 0x66a4b78 in v8::internal::Heap::CollectAllGarbage(int, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1069:3
#9 0x66a4725 in v8::internal::Heap::HandleGCRequest() out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:993:5
#10 0x659cb9a in v8::internal::StackGuard::HandleInterrupts() out/linux-x64x11-v8_debug/../../v8/src/execution.cc:480:23
#11 0x710ac22 in v8::internal::__RT_impl_Runtime_StackGuard(v8::internal::Arguments, v8::internal::Isolate*) out/linux-x64x11-v8_debug/../../v8/src/runtime/runtime-internal.cc:306:34
#12 0x710a4f3 in v8::internal::Runtime_StackGuard(int, v8::internal::Object**, v8::internal::Isolate*) out/linux-x64x11-v8_debug/../../v8/src/runtime/runtime-internal.cc:296:1
#13 0x7f36af5047a3 (<unknown module>)
0x60c0001687c0 is located 0 bytes inside of 120-byte region [0x60c0001687c0,0x60c000168838)
freed by thread T30 (MainWebModule) here:
#0 0x2308fd2 in operator delete(void*) (out/linux-x64x11-v8_debug/cobalt+0x2308fd2)
#1 0x3b532d1 in cobalt::dom::KeyboardEvent::~KeyboardEvent() out/linux-x64x11-v8_debug/../../cobalt/dom/keyboard_event.h:99:29
#2 0x238f94c in base::RefCounted<cobalt::script::Wrappable>::Release() const out/linux-x64x11-v8_debug/../../base/memory/ref_counted.h:91:7
#3 0x24ced4f in scoped_refptr<cobalt::script::Wrappable>::~scoped_refptr() out/linux-x64x11-v8_debug/../../base/memory/ref_counted.h:249:13
#4 0xb928ca2 in cobalt::script::v8c::WrapperPrivate::~WrapperPrivate() out/linux-x64x11-v8_debug/../../cobalt/script/v8c/wrapper_private.h:86:3
#5 0xb9285ba in cobalt::script::v8c::WrapperPrivate::Callback(v8::WeakCallbackInfo<cobalt::script::v8c::WrapperPrivate> const&) out/linux-x64x11-v8_debug/../../cobalt/script/v8c/wrapper_private.h:38:5
#6 0x667f45c in v8::internal::GlobalHandles::PendingPhantomCallback::Invoke(v8::internal::Isolate*) out/linux-x64x11-v8_debug/../../v8/src/global-handles.cc:848:3
#7 0x6680408 in v8::internal::GlobalHandles::DispatchPendingPhantomCallbacks(bool) out/linux-x64x11-v8_debug/../../v8/src/global-handles.cc:813:16
#8 0x668084b in v8::internal::GlobalHandles::PostGarbageCollectionProcessing(v8::internal::GarbageCollector, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/global-handles.cc:869:18
#9 0x66a8a7b in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1601:37
#10 0x66a6c48 in v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) out/linux-x64x11-v8_debug/../../v8/src/heap/heap.cc:1216:11
#11 0x65bdfc9 in v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) out/linux-x64x11-v8_debug/../../v8/src/factory.cc:91:3
#12 0x710c27d in v8::internal::__RT_impl_Runtime_AllocateInNewSpace(v8::internal::Arguments, v8::internal::Isolate*) out/linux-x64x11-v8_debug/../../v8/src/runtime/runtime-internal.cc:322:31
#13 0x710b9c3 in v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) out/linux-x64x11-v8_debug/../../v8/src/runtime/runtime-internal.cc:315:1
#14 0x7f36af5047a3 (<unknown module>)
#15 0x7f36af5513fb (<unknown module>)
#16 0x7f36af5be594 (<unknown module>)
#17 0x7f36af5b583e (<unknown module>)
#18 0x7f36af5be594 (<unknown module>)
#19 0x7f36af5b583e (<unknown module>)
#20 0x7f36af5be594 (<unknown module>)
#21 0x7f36af5bb818 (<unknown module>)
#22 0x7f36af5040fe (<unknown module>)
#23 0x6599b9a in v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, bool, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Handle<v8::internal::Object>, v8::internal::Execution::MessageHandling) out/linux-x64x11-v8_debug/../../v8/src/execution.cc:146:13
#24 0x6598454 in v8::internal::(anonymous namespace)::CallInternal(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Execution::MessageHandling) out/linux-x64x11-v8_debug/../../v8/src/execution.cc:182:10
#25 0x6597dd6 in v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) out/linux-x64x11-v8_debug/../../v8/src/execution.cc:192:10
#26 0x54a5627 in v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) out/linux-x64x11-v8_debug/../../v8/src/api.cc:5449:7
#27 0xb96677e in cobalt::dom::V8cEventListener::HandleEvent(scoped_refptr<cobalt::script::Wrappable> const&, scoped_refptr<cobalt::dom::Event> const&, bool*) const out/linux-x64x11-v8_debug/gen/bindings/browser/source/cobalt/dom/v8c_event_listener.cc:90:20
#28 0x3a2962b in cobalt::dom::EventListener::HandleEvent(scoped_refptr<cobalt::dom::Event> const&, cobalt::dom::EventListener::Type) const out/linux-x64x11-v8_debug/../../cobalt/dom/event_listener.cc:95:7
#29 0x3a1e705 in cobalt::dom::EventTarget::FireEventOnListeners(scoped_refptr<cobalt::dom::Event> const&) out/linux-x64x11-v8_debug/../../cobalt/dom/event_target.cc:200:31
previously allocated by thread T30 (MainWebModule) here:
#0 0x23083d2 in operator new(unsigned long) (out/linux-x64x11-v8_debug/cobalt+0x23083d2)
#1 0x24b530b in cobalt::browser::WebModule::Impl::InjectKeyboardEvent(scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&) out/linux-x64x11-v8_debug/../../cobalt/browser/web_module.cc:791:7
#2 0x253ca5e in base::internal::RunnableAdapter<void (cobalt::browser::WebModule::Impl::*)(scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&)>::Run(cobalt::browser::WebModule::Impl*, scoped_refptr<cobalt::dom::Element> const&, base::Token const&, cobalt::dom::KeyboardEventInit const&) out/linux-x64x11-v8_debug/../../base/bind_internal.h:317:12
#3 0x2556929 in base::internal::InvokeHelper<false, void, base::internal::RunnableAdapter<void (cobalt::browser::WebModule::Impl::*)(scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&)>, void (cobalt::browser::WebModule::Impl*, cobalt::dom::Element*, base::Token const&, cobalt::dom::KeyboardEventInit const&)>::MakeItSo(base::internal::RunnableAdapter<void (cobalt::browser::WebModule::Impl::*)(scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&)>, cobalt::browser::WebModule::Impl*, cobalt::dom::Element*, base::Token const&, cobalt::dom::KeyboardEventInit const&) out/linux-x64x11-v8_debug/../../base/bind_internal.h:966:14
#4 0x25565d6 in base::internal::Invoker<4, base::internal::BindState<base::internal::RunnableAdapter<void (cobalt::browser::WebModule::Impl::*)(scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&)>, void (cobalt::browser::WebModule::Impl*, scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&), void (base::internal::UnretainedWrapper<cobalt::browser::WebModule::Impl>, scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit)>, void (cobalt::browser::WebModule::Impl*, scoped_refptr<cobalt::dom::Element>, base::Token, cobalt::dom::KeyboardEventInit const&)>::Run(base::internal::BindStateBase*) out/linux-x64x11-v8_debug/../../base/bind_internal.h:1571:12
#5 0x2322063 in base::Callback<void ()>::Run() const out/linux-x64x11-v8_debug/../../base/callback.h:412:12
#6 0x25d3932 in MessageLoop::RunTask(base::PendingTask const&) out/linux-x64x11-v8_debug/../../base/message_loop.cc:548:21
#7 0x25d41f9 in MessageLoop::DeferOrRunPendingTask(base::PendingTask const&) out/linux-x64x11-v8_debug/../../base/message_loop.cc:560:5
#8 0x25d451e in MessageLoop::DoWork() out/linux-x64x11-v8_debug/../../base/message_loop.cc:744:13
#9 0x25f1e1b in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) out/linux-x64x11-v8_debug/../../base/message_pump_default.cc:31:31
#10 0x25d2648 in MessageLoop::RunInternal() out/linux-x64x11-v8_debug/../../base/message_loop.cc:491:10
#11 0x25d23f4 in MessageLoop::RunHandler() out/linux-x64x11-v8_debug/../../base/message_loop.cc:463:3
#12 0x265e81f in base::RunLoop::Run() out/linux-x64x11-v8_debug/../../base/run_loop.cc:47:10
#13 0x25d0cbc in MessageLoop::Run() out/linux-x64x11-v8_debug/../../base/message_loop.cc:363:12
#14 0x26f2398 in base::Thread::Run(MessageLoop*) out/linux-x64x11-v8_debug/../../base/threading/thread.cc:159:17
#15 0x26f28a3 in base::Thread::ThreadMain() out/linux-x64x11-v8_debug/../../base/threading/thread.cc:212:5
#16 0x26e58bc in base::(anonymous namespace)::ThreadFunc(void*) out/linux-x64x11-v8_debug/../../base/threading/platform_thread_starboard.cc:44:13
#17 0x2d1f982 in (anonymous namespace)::ThreadFunc(void*) out/linux-x64x11-v8_debug/../../starboard/shared/pthread/thread_create.cc:73:10
#18 0x7f37370ab183 in start_thread /build/eglibc-ripdx6/eglibc-2.19/nptl/pthread_create.c:312
Thread T30 (MainWebModule) created by T0 here:
#0 0x22c381d in __interceptor_pthread_create (out/linux-x64x11-v8_debug/cobalt+0x22c381d)
#1 0x2d1f489 in SbThreadCreate out/linux-x64x11-v8_debug/../../starboard/shared/pthread/thread_create.cc:124:12
#2 0x26e5504 in base::(anonymous namespace)::CreateThread(unsigned long, SbThreadPriority, int, bool, char const*, base::PlatformThread::Delegate*, unsigned long*) out/linux-x64x11-v8_debug/../../base/threading/platform_thread_starboard.cc:59:21
#3 0x26e5787 in base::PlatformThread::CreateWithOptions(base::PlatformThread::PlatformThreadOptions const&, base::PlatformThread::Delegate*, unsigned long*) out/linux-x64x11-v8_debug/../../base/threading/platform_thread_starboard.cc:142:10
#4 0x26f195e in base::Thread::StartWithOptions(base::Thread::Options const&) out/linux-x64x11-v8_debug/../../base/threading/thread.cc:96:8
#5 0x24bb450 in cobalt::browser::WebModule::WebModule(GURL const&, base::ApplicationState, base::Callback<void (cobalt::layout::LayoutManager::LayoutResults const&)> const&, base::Callback<void (GURL const&, std::string const&)> const&, base::Callback<void (base::TimeDelta)> const&, base::Callback<void ()> const&, cobalt::media::CanPlayTypeHandler*, cobalt::media::WebMediaPlayerFactory*, cobalt::network::NetworkModule*, cobalt::math::Size const&, float, cobalt::render_tree::ResourceProvider*, float, cobalt::browser::WebModule::Options const&) out/linux-x64x11-v8_debug/../../cobalt/browser/web_module.cc:1226:11
#6 0x23495ab in cobalt::browser::BrowserModule::Navigate(GURL const&) out/linux-x64x11-v8_debug/../../cobalt/browser/browser_module.cc:519:25
#7 0x2343f7c in cobalt::browser::BrowserModule::BrowserModule(GURL const&, base::ApplicationState, base::EventDispatcher*, cobalt::account::AccountManager*, cobalt::browser::BrowserModule::Options const&) out/linux-x64x11-v8_debug/../../cobalt/browser/browser_module.cc:372:3
#8 0x23124f7 in cobalt::browser::Application::Application(base::Callback<void ()> const&, bool) out/linux-x64x11-v8_debug/../../cobalt/browser/application.cc:614:11
#9 0x230cb48 in (anonymous namespace)::StartApplication(int, char**, char const*, base::Callback<void ()> const&) out/linux-x64x11-v8_debug/../../cobalt/browser/main.cc:78:25
#10 0x230c0b2 in void cobalt::wrap_main::BaseEventHandler<&(anonymous namespace)::PreloadApplication, &(anonymous namespace)::StartApplication, &(anonymous namespace)::HandleStarboardEvent, &(anonymous namespace)::StopApplication>(SbEvent const*) out/linux-x64x11-v8_debug/../../cobalt/base/wrap_main_starboard.h:74:7
#11 0x230b214 in SbEventHandle out/linux-x64x11-v8_debug/../../cobalt/browser/main.cc:105:1
#12 0x2d246b4 in starboard::shared::starboard::Application::DispatchAndDelete(starboard::shared::starboard::Application::Event*) out/linux-x64x11-v8_debug/../../starboard/shared/starboard/application.cc:307:3
#13 0x2d23685 in starboard::shared::starboard::Application::DispatchStart() out/linux-x64x11-v8_debug/../../starboard/shared/starboard/application.cc:194:3
#14 0x2d2242b in starboard::shared::starboard::Application::RunLoop() out/linux-x64x11-v8_debug/../../starboard/shared/starboard/application.cc:382:5
#15 0x2d228b8 in starboard::shared::starboard::Application::Run(starboard::shared::starboard::CommandLine) out/linux-x64x11-v8_debug/../../starboard/shared/starboard/application.cc:111:10
#16 0x277ca1f in starboard::shared::starboard::Application::Run(int, char**) out/linux-x64x11-v8_debug/../../starboard/shared/starboard/application.h:166:12
#17 0x277c849 in main out/linux-x64x11-v8_debug/../../starboard/linux/x64x11/main.cc:31:26
#18 0x7f37360cff44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287
SUMMARY: AddressSanitizer: heap-use-after-free out/linux-x64x11-v8_debug/../../cobalt/script/v8c/v8c_heap_tracer.cc:76:16 in cobalt::script::v8c::V8cHeapTracer::AdvanceTracing(double, v8::EmbedderHeapTracer::AdvanceTracingActions)
Shadow bytes around the buggy address:
0x0c18800250a0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
0x0c18800250b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c18800250c0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c18800250d0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
0x0c18800250e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x0c18800250f0: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd
0x0c1880025100: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
0x0c1880025110: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c1880025120: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c1880025130: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
0x0c1880025140: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==184290==ABORTING
Вывод журнала (регистрация начала / конца цикла GC, маркировка объекта и выполнение слабого обратного вызова):
$ cat log.txt | grep -P '(Begin|End|0x60c000199540)'
[0204/150945:INFO:v8c_heap_tracer.cc(53)] Begin GC cycle 1
[0204/151001:INFO:v8c_heap_tracer.cc(37)] 0x60c000199540 got registered by RegisterV8References during GC cycle 1
[0204/151001:INFO:v8c_heap_tracer.cc(172)] 0x60c000199540 got marked during GC cycle 1
[0204/151001:INFO:wrapper_private.h(78)] 0x60c000199540 is dying in GC cycle 1
==190737==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000199540 at pc 0x0000053ad9de bp 0x7fe4ebb76270 sp 0x7fe4ebb76268
READ of size 8 at 0x60c000199540 thread T30 (MainWebModule)
0x60c000199540 is located 0 bytes inside of 120-byte region [0x60c000199540,0x60c0001995b8)
1 ответ
В конфигурации по умолчанию V8 помечает оболочки, т.е. объекты, указывающие в память устройства для вставки, постепенно.
Требования
-
v8::EmbedderHeapTracer
реализация, выясняющая (переходную) жизнеспособность оболочек V8 на основе ссылок, переданных ей из V8. - Механизмы согласованности, например, барьеры записи, когда DOM изменяется во время инкрементной маркировки.
- Информирование сборщика мусора молодого поколения V8, чтобы сохранить
v8::Persistent
жив во время инкрементальной маркировки.
3, вероятно, неуловимо. Шаги включают в себя:
Зарегистрируйте обратный вызов для Scavenges, используя
Isolate::AddGCPrologueCallback
Посетите слабые постоянные ручки, используя
Isolate::VisitWeakHandles
Пометить слабые персистенты как активные, используя
v8::PersistentBase<T>::MarkActive
Шаги 2 и 3 могут быть пропущены при отключении инкрементной трассировки оболочек с использованием флага incremental_marking_wrappers
,