GC entry deadlock on AArch64/Darwin
While debugging Haddock segfaults on AArch64/Darwin I noticed that sometimes the Haddock process would hang when entering GC, particularly when linked against the debug RTS. Specifically the relevant backtraces are:
(lldb) bt all
* thread #1, name = 'ghc_worker', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x000000018f54d328 libsystem_kernel.dylib`mach_absolute_time + 72
frame #1: 0x000000018f54ecc0 libsystem_kernel.dylib`__commpage_gettimeofday_internal + 44
frame #2: 0x000000018f467f84 libsystem_c.dylib`gettimeofday + 52
frame #3: 0x000000018f458268 libsystem_c.dylib`_mach_boottime_usec + 136
frame #4: 0x000000018f4583a0 libsystem_c.dylib`clock_gettime + 200
frame #5: 0x000000010527eeb8 haddock`getProcessElapsedTime [inlined] getClockTime(clock=_CLOCK_MONOTONIC) at GetTime.c:62:15 [opt]
frame #6: 0x000000010527eeac haddock`getProcessElapsedTime [inlined] getMonotonicNSec at GetTime.c:148 [opt]
frame #7: 0x000000010527eeac haddock`getProcessElapsedTime at GetTime.c:170 [opt]
* frame #8: 0x00000001052708c8 haddock`waitForGcThreads(cap=0x000000010a01d400, idle_cap=0x0000000109304470) at GC.c:1453:14 [opt]
frame #9: 0x000000010525bb44 haddock`scheduleDoGC(pcap=0x000000016fdf92b0, task=0x0000000109210410, force_major=false, is_overflow_gc=true, deadlock_detect=false) at Schedule.c:1816:9 [opt]
frame #10: 0x000000010525b2fc haddock`schedule(initialCapability=<unavailable>, task=0x0000000109210410) at Schedule.c:579:7 [opt]
frame #11: 0x000000010525aa28 haddock`scheduleWaitThread(tso=0x0000007000406ce8, ret=<unavailable>, pcap=0x000000016fdf9350) at Schedule.c:2651:11 [opt]
frame #12: 0x000000010525535c haddock`rts_evalLazyIO(cap=<unavailable>, p=<unavailable>, ret=<unavailable>) at RtsAPI.c:566:5 [opt] [artificial]
frame #13: 0x0000000105257680 haddock`hs_main(argc=366, argv=0x000000016fdf9560, main_closure=<unavailable>, rts_config=<unavailable>) at RtsMain.c:72:9 [opt]
frame #14: 0x00000001003d16e0 haddock`main + 156
frame #15: 0x000000018f5a5450 libdyld.dylib`start + 4
...
thread #4, name = 'ghc_worker'
frame #0: 0x000000018f54fa48 libsystem_kernel.dylib`__psynch_mutexwait + 8
frame #1: 0x000000018f584918 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 88
frame #2: 0x000000018f582244 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 232
frame #3: 0x000000010527046c haddock`gcWorkerThread(cap=0x0000000105e6d5c0) at GC.c:1364:5 [opt]
frame #4: 0x000000010524aa04 haddock`yieldCapability(pCap=0x000000016ff9eee8, task=0x0000000109210670, gcAllowed=<unavailable>) at Capability.c:971:21 [opt]
frame #5: 0x000000010525acb4 haddock`schedule [inlined] scheduleYield(pcap=0x000000016ff9eee0, task=0x0000000109210670) at Schedule.c:705:25 [opt]
frame #6: 0x000000010525ac64 haddock`schedule(initialCapability=<unavailable>, task=0x0000000109210670) at Schedule.c:315 [opt]
frame #7: 0x000000010525b474 haddock`scheduleWorker(cap=0x0000000105e6d5c0, task=0x0000000109210670) at Schedule.c:2668:11 [opt]
frame #8: 0x0000000105260d00 haddock`workerStart(task=0x0000000109210670) at Task.c:445:5 [opt]
frame #9: 0x000000018f587878 libsystem_pthread.dylib`_pthread_start + 320
Thread 1 is waiting for all worker threads to join the GC (where n_gc_threads == 1
and n_gc_entered == 0
) and thread 4 is blocked on the gc_entry_mutex
.