Skip to content

nonmovingTidyWeaks segfaults if w->key is static data

Summary

nonmovingTidyWeaks has the following line: https://gitlab.haskell.org/ghc/ghc/-/blob/d3a050d2a1eac0244f989badb3a2c75c84e0a160/rts/sm/NonMovingMark.c?page=3#L2014

bool key_in_nonmoving = Bdescr((StgPtr) w->key)->flags & BF_NONMOVING;

Here we check if the block descriptor of the key puts it in the nonmoving heap. But if w->key is static data and lives in the executables .data section, we may get a segfault trying to look up the Bdescr.

I saw segfaults when testing my WIP branch for #24150 (closed) using the nonmoving_thr way when running the GcStaticPointers test. I checked and it also happens with master but not with my boot compiler which is ghc-9.6.2.

Steps to reproduce

Run the GcStaticPointers in the nonmoving_thr way. I am using the release+debug_info flavour but I'm not sure if that's relevant. It will segfault with this backtrace:

Thread 7 "nonmoving-mark" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffdffff6c0 (LWP 2028996)]
0x00000000004996ac in nonmovingTidyWeaks (queue=queue@entry=0x7fffb8000bc0) at rts/sm/NonMovingMark.c:2015
2015            if (!key_in_nonmoving || nonmovingIsNowAlive(w->key)) {
(gdb) bt
#0  0x00000000004996ac in nonmovingTidyWeaks (queue=queue@entry=0x7fffb8000bc0) at rts/sm/NonMovingMark.c:2015
#1  0x0000000000495cb5 in nonmovingMarkThreadsWeaks (mark_queue=0x7fffb8000bc0, budget=0x7fffdfffee70) at rts/sm/NonMoving.c:870
#2  nonmovingMark_ (mark_queue=mark_queue@entry=0x7fffb8000bc0, dead_weaks=dead_weaks@entry=0x7fffdfffeeb8, resurrected_threads=resurrected_threads@entry=0x7fffdfffeec0,
    concurrent=concurrent@entry=true) at rts/sm/NonMoving.c:1077
#3  0x000000000049607d in nonmovingConcurrentMarkWorker (data=<optimized out>) at rts/sm/NonMoving.c:933
#4  nonmovingConcurrentMarkWorker (data=<optimized out>) at rts/sm/NonMoving.c:910
#5  0x00007ffff7cdee64 in start_thread () from /nix/store/9v5d40jyvmwgnq1nj8f19ji2rcc5dksd-glibc-2.37-45/lib/libc.so.6
#6  0x00007ffff7d609f0 in clone3 () from /nix/store/9v5d40jyvmwgnq1nj8f19ji2rcc5dksd-glibc-2.37-45/lib/libc.so.6
(gdb) p *w
$1 = {header = {info = 0x4a9810 <stg_WEAK_info>}, cfinalizers = 0x5101c8, key = 0x502570, value = 0x502570, finalizer = 0x502620, link = 0x4201868408}
(gdb) p Bdescr(w->key)
800
    52688     18624     39240$2 = (bdescr *) 0x500080

And note that the address lies in the .data section of the executable.

Expected behavior

Not segfault.

Environment

  • GHC version used: 9.9.20240221
Edited by Teo Camarasu
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information