Странное поведение от использования 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 помечает оболочки, т.е. объекты, указывающие в память устройства для вставки, постепенно.

Требования

  1. v8::EmbedderHeapTracer реализация, выясняющая (переходную) жизнеспособность оболочек V8 на основе ссылок, переданных ей из V8.
  2. Механизмы согласованности, например, барьеры записи, когда DOM изменяется во время инкрементной маркировки.
  3. Информирование сборщика мусора молодого поколения V8, чтобы сохранить v8::Persistent жив во время инкрементальной маркировки.

3, вероятно, неуловимо. Шаги включают в себя:

  • Зарегистрируйте обратный вызов для Scavenges, используя Isolate::AddGCPrologueCallback

  • Посетите слабые постоянные ручки, используя Isolate::VisitWeakHandles

  • Пометить слабые персистенты как активные, используя v8::PersistentBase<T>::MarkActive

Шаги 2 и 3 могут быть пропущены при отключении инкрементной трассировки оболочек с использованием флага incremental_marking_wrappers,

Другие вопросы по тегам