В ripgrep 15.2.0, собранном под x86_64-unknown-linux-musl, обнаружилась неприятная ошибка — SIGSEGV при параллельном поиске на очень больших файловых деревьях. Пользователь наткнулся на неё в бинарнике из поставки OpenAI Codex, но затем воспроизвёл и на официальном релизном архиве с GitHub, и на собственноручно собранном с дебаг-символами через cross + podman.
Крэш происходит внутри аллокатора MUSL — mallocng. В бэктрейсе видно, что при вызове calloc из opendir срабатывает проверка целостности метаданных кучи (get_meta), которая и роняет процесс. Выше по стеку — штатный обход директорий в ignore::walk, многопоточный воркер запускает read_dir, а Rust через small_c_string дёргает opendir.
Для воспроизведения нужно по-настоящему огромное дерево. Пользователь приложил generate_repro_tree.py — сгенерированный LLM скрипт, который создаёт около 20 GiB данных в 1,8 миллиона файлов, имитируя статистику реального репозитория. Дальше из корня этого дерева в бесконечном цикле запускается rg с поиском заведомо отсутствующей строки: while true; do rg tnoheueunotshisnthukoethnsueothnsiuothonesuioseuinth; done. На 24-ядерной машине с достаточным объёмом свободной RAM, чтобы дерево целиком легло в блок-кэш ядра, падение случается примерно через минуту.
Баг стабильно проявляется только при высокой степени параллелизма и именно в musl-сборке. В системах с glibc такого не наблюдается. Версия ripgrep свежая — 15.2.0 (rev e89fff8), с фичами +pcre2 и рантайм-поддержкой SIMD (SSE2, SSSE3, AVX2). Ожидаемое поведение — обычный завершённый поиск без segfault, а не падение с испорченной кучей.
Судя по тому, что ошибка вылезает именно в calloc внутри opendir, причину стоит искать либо в гонке внутри самого mallocng при высоконагруженном выделении памяти, либо в том, как ripgrep (точнее, крейт ignore) обрабатывает возвращаемые opendir дескрипторы в многопоточном режиме. Пока проблема остаётся открытой, и любой желающий может воспроизвести её с помощью приложенных скрипта и бинарников.