Hello Omer,
Thank you for your quick reply.
In my scenario, the dispose of the v8::Isolate is never called, the crash occurs before :
Thread 1 begins
v8::platform::NewDefaultPlatform (from thread 1)
v8::V8::InitializePlatform
(from thread 1)
v8::V8::Initialize()
(from thread 1)
Thread 1 ends
Thread 2 and Thread 3 begin
Thread 2 locks the mutex and Thread 3 is blocked by the mutex
v8::Isolate::New (from thread 2)
Thread 2 unlocks the mutex and sleeps for 100ms
v8::Isolate::New (from thread 3) ==> Crash
About "
v8::internal::JSDispatchTable::PreAllocatedEntryNeedsInitialization":
The call stack was with the last stable release of V8 : 15.0.245.13
I tried with the last version I found 15.1.206.1, it still crashes with the same stack:
#0 0x0000000001066bcd v8::internal::JSDispatchTable::PreAllocatedEntryNeedsInitialization(v8::internal::ExternalEntityTable<v8::internal::JSDispatchEntry, 268435456ul>::Space*, v8::base::StrongAlias<v8::internal::JSDispatchHandleAliasTag, unsigned int>) (v8_isolate_repro_151 + 0xe66bcd)
#1 0x0000000000a5dff0 v8::internal::Isolate::InitializeBuiltinJSDispatchTable() (v8_isolate_repro_151 + 0x85dff0)
#2 0x0000000000a5684a v8::internal::Isolate::Init(v8::internal::SnapshotData*, v8::internal::SnapshotData*, v8::internal::SnapshotData*, bool) (v8_isolate_repro_151 + 0x85684a)
#3 0x0000000000a57079 v8::internal::Isolate::InitWithSnapshot(v8::internal::SnapshotData*, v8::internal::SnapshotData*, v8::internal::SnapshotData*, bool) (v8_isolate_repro_151 + 0x857079)
#4 0x0000000001085fda v8::internal::Snapshot::Initialize(v8::internal::Isolate*) (v8_isolate_repro_151 + 0xe85fda)
#5 0x00000000008eb8b9 v8::Isolate::Initialize(v8::Isolate*, v8::Isolate::CreateParams const&) (v8_isolate_repro_151 + 0x6eb8b9)
#6 0x00000000008ebb6b v8::Isolate::New(v8::Isolate::CreateParams const&) (v8_isolate_repro_151 + 0x6ebb6b)
#7 0x00000000008aa13c CreateAndDestroyIsolate() (v8_isolate_repro_151 + 0x6aa13c)
#8 0x00000000008ab6b2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) (v8_isolate_repro_151 + 0x6ab6b2)
#9 0x00000000008ab675 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) (v8_isolate_repro_151 + 0x6ab675)
#10 0x00000000008ab64d void std::thread::_Invoker<std::tuple<void (*)()>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) (v8_isolate_repro_151 + 0x6ab64d)
#11 0x00000000008ab625 std::thread::_Invoker<std::tuple<void (*)()>>::operator()() (v8_isolate_repro_151 + 0x6ab625)
#12 0x00000000008ab589 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()>>>::_M_run() (v8_isolate_repro_151 + 0x6ab589)
#13 0x00007fdbfb8dbae4 execute_native_thread_routine (libstdc++.so.6 + 0xdbae4)
#14 0x00007fdbfb48b3f9 start_thread (libc.so.6 + 0x8b3f9)
#15 0x00007fdbfb5105d0 __clone3 (libc.so.6 + 0x1105d0)
In which version the API "
v8::internal::JSDispatchTable::PreAllocatedEntryNeedsInitialization" gets removed ?
It seems that the crash could be related to PKU, because it crashes on RHEL9 with PKU but doesn't crash on RHEL9 without PKU.
So I did some further investigation using GDB and strace.
Under GDB, at the crash point:
(gdb) p $_siginfo.si_code
$1 = 4
I checked the Linux headers:
$ grep -R "SEGV_PKUERR" /usr/include
/usr/include/asm-generic/siginfo.h:# define SEGV_PKUERR 4 /* failed protection key checks */
So the kernel reports this as a protection key violation (SEGV_PKUERR)
I also traced the system calls:
$ strace -f ./v8_isolate_repro_151 2>&1 | grep pkey
[pid 865176] pkey_alloc(0, PKEY_DISABLE_WRITE) = 1
[pid 865176] pkey_mprotect(0x2627000, 4096, PROT_READ, 0) = 0
[pid 865176] pkey_mprotect(0x7f5d8a1ec000, 268435456, PROT_NONE, 1) = 0
[pid 865176] pkey_mprotect(0x7f5d821ec000, 134217728, PROT_NONE, 1) = 0
[pid 865176] pkey_mprotect(0x62340000, 536870912, PROT_READ|PROT_WRITE|PROT_EXEC, 1) = 0
[pid 865194] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_PKUERR, si_addr=0x7f5d8a1ec010, si_pkey=1} ---
Also I found others related issues:
https://github.com/denoland/rusty_v8/issues/1381https://github.com/denoland/deno_core/issues/1091