Ripgrep: musl-сборки падают в сегфолт при поиске по гигантским деревьям файлов

Ripgrep: musl-сборки падают в сегфолт при поиске по гигантским деревьям файлов

В репозитории BurntSushi/ripgrep на GitHub завели issue #3494: сборки ripgrep для целевой платформы x86_64-unknown-linux-musl изредка аварийно завершаются с сигналом SIGSEGV при поиске по очень большим деревьям файлов и высокой степени конкурентности. Баг воспроизведён на ripgrep 15.2.0 (rev e89fff8, с включённым pcre2) на OpenSUSE Tumbleweed Linux x86_64. Автор багрепорта впервые столкнулся с падением в rg, который поставляется вместе с OpenAI Codex, но показал, что этот бинарник побайтово идентичен официальному релизу ripgrep 15.2.0 для musl с GitHub, и воспроизвёл падение независимо от Codex.

По словам автора, крашащаяся строка, это проверка целостности метаданных кучи внутри аллокатора mallocng, встроенного в musl; она срабатывает в вызове calloc, который делает функция opendir. Автор собрал ripgrep с отладочными символами (через cross в контейнере podman, с CARGO_PROFILE_RELEASE_DEBUG=true) и приложил полный бэктрейс: падение происходит в get_meta() внутри mallocng, вызывается из calloc → opendir → чтения директории в стандартной библиотеке Rust → обхода дерева в крейте ignore (том самом, что использует ripgrep для обхода файловой системы) → рабочего потока воркер-пула.

Для воспроизведения нужно достаточно большое дерево файлов, по словам автора, это ключевое условие. Он использовал написанный с помощью нейросети скрипт generate_repro_tree.py, который создаёт дерево случайных файлов, повторяющее статистику того репозитория, где баг был впервые замечен: примерно 20 гигабайт данных в 1,8 млн файлов. Далее из корня этого дерева в цикле запускается rg с поиском произвольной строки, которой заведомо нет в дереве (while true; do rg <строка>; done). На системе с 24 ядрами и достаточным объёмом свободной памяти, чтобы дерево поместилось в файловый кеш ядра, SIGSEGV обычно появляется примерно через минуту таких запусков.

В тексте багрепорта нет ни исправления, ни ответа мейнтейнеров ripgrep, только сам репорт с бэктрейсом. Не сказано и о том, воспроизводится ли падение на сборках ripgrep, слинкованных с glibc (а не с musl), как долго существует баг и какие ещё версии ripgrep, помимо 15.2.0, подвержены проблеме.

Ключевые факты

  • В ripgrep (issue #3494 на GitHub) описан баг: сборки под x86_64-unknown-linux-musl изредка падают с SIGSEGV при поиске по очень большим деревьям файлов на высокой конкурентности.
  • Крашащаяся строка, проверка целостности метаданных кучи в аллокаторе mallocng библиотеки musl, срабатывающая в calloc внутри opendir при обходе директорий.
  • Для воспроизведения нужно большое дерево: около 20 ГБ данных в 1,8 млн файлов; на 24-ядерной системе с деревом в файловом кеше SIGSEGV обычно появляется примерно за минуту непрерывных запусков rg в цикле.
  • Автор багрепорта подтвердил, что крашащийся musl-бинарник побайтово идентичен официальному релизу ripgrep 15.2.0, и воспроизвёл падение независимо от OpenAI Codex, где впервые его заметил.
  • На момент репорта у ripgrep нет ни фикса, ни ответа мейнтейнеров, issue открыт, только бэктрейс и описание проблемы от автора.

Почему это важно

Ripgrep, один из самых распространённых инструментов поиска по коду, встроенный во многие редакторы, CI-пайплайны и ИИ-агенты (в тексте упомянут как часть OpenAI Codex). Баг с повреждением памяти в его musl-сборках, плохая новость именно потому, что musl-таргет широко используется для статически слинкованных бинарников в контейнерах и минималистичных дистрибутивах вроде Alpine Linux, а сам сбой связан не с логикой ripgrep, а с аллокатором памяти в самой библиотеке musl.

Кому это важно

В первую очередь, разработчикам, которые запускают ripgrep на musl-сборках при поиске по очень большим деревьям файлов с высокой конкурентностью: в больших монорепозиториях, в контейнерных окружениях на Alpine, а также авторам инструментов, которые встраивают ripgrep как зависимость (в тексте, пример OpenAI Codex).

Как это применить

Практических рекомендаций в источнике нет, только сам багрепорт. Разработчикам, которые сталкиваются с похожими падениями rg на musl, имеет смысл свериться с issue #3494 на GitHub и, если возможно, воспользоваться сборкой ripgrep, слинкованной с glibc, а не с musl, до появления фикса.

Можно ли доверять

Багрепорт выглядит добротным: автор приложил точную версию ripgrep, полный бэктрейс с отладочными символами, воспроизводящий скрипт и явно проверил, что упавший бинарник побайтово совпадает с официальным релизом, а не с модифицированной сборкой из Codex. При этом источник, заявка одного пользователя на GitHub без подтверждения мейнтейнеров ripgrep или разработчиков musl, так что причинно-следственная связь (баг именно в mallocng, а не в способе, которым ripgrep его использует) пока не подтверждена независимо.

Риски и подводные камни

Падение воспроизводится только при специфичных условиях, очень большое дерево файлов (миллионы файлов, десятки гигабайт) и высокая конкурентность обхода директорий, поэтому многие пользователи ripgrep с ним просто не столкнутся. В источнике не указано, какие версии ripgrep, помимо 15.2.0, подвержены проблеме, воспроизводится ли она на сборках с glibc, и нет ни срока, ни подтверждённого плана исправления.

«Сборки ripgrep для x86_64-unknown-linux-musl изредка падают с SIGSEGV при поиске по очень большим деревьям файлов на высокой конкурентности.»

— автор багрепорта, issue #3494 на GitHub