A Rare Segfault in Ripgrep’s Musl Builds Exposes Linux Kernel Race

A subtle race between Linux 7.0's munmap TLB shootdown and musl's anonymous page fault handling causes occasional segfaults in ripgrep's musl binaries during massive directory searches. Independent analysis pins the exact mechanism and points to a kernel change. The bug affects only specific builds but reveals deep interactions in modern memory management.
A Rare Segfault in Ripgrep’s Musl Builds Exposes Linux Kernel Race
A Rare Segfault in Ripgrep’s Musl Builds Exposes Linux Kernel Race
Emma Rogers

Ripgrep built the reputation as the tool developers reach for when they need to search codebases fast. BurntSushi’s creation outperforms traditional grep in most scenarios. It respects .gitignore files by default. It skips binary files without being told. And it delivers results in fractions of a second on repositories that bring other utilities to their knees.

Yet a bug report filed late last month has shaken some of that confidence. The GitHub issue #3494 describes occasional segmentation faults. They strike only the x86_64-unknown-linux-musl binaries. They appear during very large directory traversals. And they resisted quick explanation.

The reporter provided a reproducible test case. A Python script generates a directory tree of nearly two million files totaling 20 GiB. A simple command then triggers the crash roughly once every few runs.

while true; do ../rg –threads 12 tnoheueunotshisnthukoethnsueothnsiuothonesuioseuinth; echo “rc=$?”; done

The command returns 139. SIGSEGV. The backtrace always points deep inside musl’s mallocng allocator. Specifically to an integrity check inside get_meta. The crash happens early in the walk. Often within the first couple seconds.

At first glance the symptoms suggested a ripgrep bug. Or perhaps an interaction with its default regex engine. But the issue author quickly narrowed the field. The same searches run cleanly on glibc-based systems. The problem stayed musl-specific. And it showed no clear tie to the pattern itself.

The investigation that followed turned a simple bug report into a master class in systems debugging.

David Franke, operating under the handle dfoxfranke, took the artifacts attached to the issue and built an exhaustive analysis repository. His work, hosted at dfoxfranke/ripgrep-3494-analysis, pins the failure with surgical precision. The root cause sits at the boundary between the Linux kernel, musl libc, and the allocator’s handling of anonymous memory mappings.

Franke’s instrumented version of musl 1.2.5 adds logging around every relevant allocation, free, and munmap operation. It also inserts checks that detect when a thread fails to observe its own recent stores. The results stunned even seasoned observers.

In every captured crash a thread writes a small index value to a freshly allocated metadata slot. Ten instructions later the same thread reads the location again as part of a read-modify-write sequence. The read returns zero. The value written moments earlier has vanished. An immediate read right after the store sees the correct value. Only the slightly delayed read tears.

Pagemap inspection at the exact moment of the tear reveals the page backing the address is the kernel’s zero page. The virtual address has been remapped underneath the running code. A previous mapping at the same virtual address was unmapped. A new anonymous mapping took its place. The timing window for this replacement overlaps the critical store and reload sequence inside enframe.

The analysis identifies the interaction between the per-VMA-lock fast path for anonymous page faults and a concurrent munmap’s TLB shootdown as the culprit. A change introduced in Linux 7.0 widened the race window on the munmap side. Kernel version 7.0.12, the exact release running on the original reporter’s AMD Threadripper 9960X system, exposes the bug.

Discussions on Hacker News yesterday amplified the findings. Commenters noted that ripgrep’s musl build uses jemalloc as the global allocator for 64-bit targets yet still calls into musl’s opendir, which triggers calloc. That allocation can land in the precise code path that exercises the kernel race. Several engineers suggested switching to mimalloc or avoiding libc directory iteration entirely as practical workarounds.

The bug does not affect the vast majority of ripgrep users. Most developers run glibc-based distributions. The affected binaries ship primarily in static distributions and containers that prioritize size over glibc compatibility. Alpine Linux users and anyone pulling the musl tarball from the ripgrep releases page sit in the line of fire. Yet even there the crash rate stays low enough that many never encounter it.

Ripgrep’s author Andrew Gallant, known online as BurntSushi, has engaged with the thread. The issue remains open. No patch has landed yet. The complexity of the race suggests the fix may live in the kernel, in musl, or in how ripgrep performs large-scale directory walks. Changing the allocator story or replacing opendir with a custom implementation could insulate the tool.

This episode highlights deeper tensions. Memory allocators optimized for speed make different tradeoffs than those built for absolute robustness. Musl’s mallocng prioritizes small binary size and low memory overhead. Its design assumes the kernel provides coherent page fault and TLB behavior. When that assumption breaks, the failure looks like a memory corruption bug even though the allocator code itself is correct.

Developers who rely on ripgrep for massive monorepo searches or log analysis should take note. The musl binaries remain fast. They simply carry a small but real risk on recent kernels with specific hardware and workload combinations. Switching to the glibc build or using the cargo-installed version sidesteps the problem for now.

Franke’s analysis stands as one of the clearest technical write-ups of a kernel-user space interaction in recent memory. It combines disassembly, instrumentation, pagemap probing, and kernel source archaeology. The repo even includes patches that eliminate the crash when they lengthen the critical path enough to close the race window. Those same patches confirm the timing sensitivity. Adding an mfence or extra function call drops the reproduction rate to zero in controlled tests.

The story also reveals how quickly modern open source projects surface and dissect subtle bugs. Within days of the initial report an independent researcher produced a reproducible environment, an instrumented libc, and a diagnosis that points directly at a Linux 7.0 regression. The tools available to today’s systems programmers have grown powerful. So has the community that knows how to wield them.

Ripgrep will almost certainly emerge stronger. A workaround or kernel fix will land. Users who hit the crash can already avoid it. And the entire ecosystem gains a detailed case study in how virtual memory, TLB shootdowns, and allocator metadata interact under extreme scale.

The tool that made recursive search feel instantaneous still does. Just not on every platform. Not every time. Not yet.

Subscribe for Updates

DevNews Newsletter

The DevNews Email Newsletter is essential for software developers, web developers, programmers, and tech decision-makers. Perfect for professionals driving innovation and building the future of tech.

By signing up for our newsletter you agree to receive content related to ientry.com / webpronews.com and our affiliate partners. For additional information refer to our terms of service.

Notice an error?

Help us improve our content by reporting any issues you find.

Get the WebProNews newsletter delivered to your inbox

Get the free daily newsletter read by decision makers

Subscribe
Advertise with Us

Ready to get started?

Get our media kit

Advertise with Us