Assertion failure while changing priority of worker thread during GC
tlbtlbtlb opened this issue · 0 comments
tlbtlbtlb commented
Doing this causes occasional assertion failures deep inside v8:
var gc = (require('gc-stats'))();
gc.on('stats', function (stats) {
console.log('GC ' +
((stats.gctype&1) ? 'scavenge ' : '') +
((stats.gctype&2) ? 'marksweepcompact ' : '') +
((stats.gctype&4) ? 'incrementalmarking ' : '') +
((stats.gctype&8) ? 'weakcallbacks ' : '') +
((stats.gctype&0xfffffff0) ? ('0x' + stats.gctype.toString(16) + ' ') : '') +
(stats.pause/1000000.0).toFixed(1) + 'mS ' +
(stats.diff.usedHeapSize/1048576).toFixed(1) + 'M ' +
(stats.after.usedHeapSize/1048576).toFixed(1) + 'M');
});
- Version:
Node v8.1.0 - Platform:
Linux london 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
I get the following assertion failure:
node: tpp.c:84: __pthread_tpp_change_priority: Assertion `new_prio == -1 || (new_prio >= fifo_min_prio && new_prio <= fifo_max_prio)' failed.
and gdb gives this backtrace:
Thread 5 "V8 WorkerThread" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff5340700 (LWP 20368)]
0x00007ffff6b79428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff6b79428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff6b7b02a in __GI_abort () at abort.c:89
#2 0x00007ffff6b71bd7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x7ffff6f20598 "new_prio == -1 || (new_prio >= fifo_min_prio && new_prio <= fifo_max_prio)",
file=file@entry=0x7ffff6f2058c "tpp.c", line=line@entry=84, function=function@entry=0x7ffff6f20650 <__PRETTY_FUNCTION__.7703> "__pthread_tpp_change_priority") at assert.c:92
#3 0x00007ffff6b71c82 in __GI___assert_fail (assertion=assertion@entry=0x7ffff6f20598 "new_prio == -1 || (new_prio >= fifo_min_prio && new_prio <= fifo_max_prio)",
file=file@entry=0x7ffff6f2058c "tpp.c", line=line@entry=84, function=function@entry=0x7ffff6f20650 <__PRETTY_FUNCTION__.7703> "__pthread_tpp_change_priority") at assert.c:101
#4 0x00007ffff6f1f029 in __pthread_tpp_change_priority (previous_prio=previous_prio@entry=-1, new_prio=new_prio@entry=0) at tpp.c:82
#5 0x00007ffff6f1687c in __pthread_mutex_lock_full (mutex=0xe19ec80) at ../nptl/pthread_mutex_lock.c:456
#6 0x0000000000f11b7f in v8::internal::MemoryChunk::ReleaseTypedOldToOldSlots() ()
#7 0x0000000000ef3422 in v8::internal::PageParallelJob<v8::internal::PointerUpdateJobTraits<(v8::internal::PointerDirection)0> >::Task::RunInternal() ()
#8 0x0000000000b7130d in v8::internal::CancelableTask::Run() ()
#9 0x000000000148a479 in v8::platform::WorkerThread::Run() ()
#10 0x00000000016136a0 in ?? ()
#11 0x00007ffff6f146ba in start_thread (arg=0x7ffff5340700) at pthread_create.c:333
#12 0x00007ffff6c4a82d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
MemoryChunk::ReleaseTypedOldToOldSlots() references a base::AtomicValue<TypedSlotSet*>, which is why pthread_mutex gets involved.
I believe the root cause is calling uv_queue_work
from the GC callback. uv_queue_work
isn't safe to use from outside the main thread. You really want the uv_async
system, which is intended for triggering work from a non-main thread (like the GC thread) and having it executed on the main thread.