Как стать автором
Обновить

Не пора ли валить с gnu libc на что‑то другое?

Уровень сложностиСредний
Время на прочтение3 мин
Количество просмотров21K

Пользуюсь открытым ПО значительное время. Сижу на Линуксе.

Но в последнее время настолько часто сталкиваюсь с различными багами, что думается иногда, а как оно вообще в принципе работает?

Последний эпизод коснулся совсем уж системного кода - стандартной библиотеки libc от GNU. Системнее может быть только ядро.


История такая. Собрал Хромиум (не быстро). Когда наконец сборка завершилась с попутным решением проблем, думал: ну вот наконец щас запущу, посмотрю как работают интересующие меня вещи. И тут произошёл облом. Хром падал почти в самом начале запуска с ошибкой доступа к памяти. Довольно быстро удалось выяснить, что падение происходит из-за ошибки обращения по нулевому указателю. И происходит оно в динамическом загрузчике, то бишь в libdl, при загрузке библиотеки через dlopen. libdl.so является одной из компонент пакета стандартной библиотеки и понятно, самой системной библиотекой в ОС. Подробности всей ситуации я описал в вопросе на stackoverflow.

Вкратце: при загрузке библиотеки libXcursor.so подтягиваются непонятно откуда взявшиеся зависимости, не имеющие никакого отношения к упомянутой библиотеке. И зависимости эти не инициализированы корректно. Откуда и происходит обращение по нулевому указателю. Впоследствии выяснилось, что проблема начинается с несовпадающих версий библиотек libQt5Core, в результате чего libdl делает полный отбой с попыткой отката всех изменений.

Но, видимо, этот откат реализован из рук вон плохо, поскольку после него начинают происходить весьма странные вещи. И загрузка неинициализированной зависимости с нулевыми указателями лишь одна из них. Я ещё сделал пробник в виде простого приложения, которое пытается воспроизвести ситуацию. И в этом пробнике также происходил сбой, но уже при инициализации (вызов init или конструктор в их терминологии) либы libpthread.so (тоже очень системная) - потерян адрес глобального на процесс хранилища либ.

Что меня разочаровывает сильнее всего в этой истории - это то, что загрузчик находится в невалидном состоянии и продолжает в этом состоянии работать, никак его не детектируя. И понятно почему - код практически везде лишён каких-либо проверок на ошибки. Тот же самый нулевой указатель можно было бы отловить заранее, но он используется без проверки, да ещё в цикле. Ситуация усугубляется широким использованием макросов, которые вроде как должны помочь избежать дублирования кода (для тех кто не в курсе - код написан конечно на Си). Но в этом, например, случае макрос используется всего для 2 вариантов кода. Проблема в том, что в таких макросах трудно сделать проверку на ошибки и самое главное - корректно вернуть её. То есть сам дизайн кода не способствует его качеству и затрудняет корректное изменение кода в случае такой надобности.

Да, я не сказал, что это не самая свежая версия glibc - 2.27. Да, в версии 2.32 проблема вроде бы не воспроизводится, потому что упомянутые участки кода были изменены - были внесены более-менее адекватные правки, которые в том числе удалили размещение огромных массивов на стеке, поменяли логику загрузки зависимостей. Но проблема в том, что эта логика, весьма странная логика, скажем честно, там была. Складывается впечатление, что те, кто вносили изменения в этот код до 2020 года, вообще плохо представляли как оно всё работает. Это в принципе подрывает доверие к всему проекту: непонятно, кто и почему вносит вносит изменения в столь критически важный системный код.

Плюс отсутствие проверок на ошибки.

Недавно я натолкнулся на анонс РедХат о несовместимых изменениях в сабже (Why glibc 2.34 removed libpthread), в котором делается ссылка на либу libmusl, как на авторитетный пример для подражания. Смотрите, дескать, вот у них получилось, давайте и мы так сделаем. Так может быть, действительно мюсл уже в таком состоянии, что по качеству превосходит ГНУ либси?

Если посмотреть на использование совместимой кодовой базы в коммерческих целях, то на ум сразу приходит libbionic. Это основная системная либа в гаджетах на Linux-совместимом Андроиде. Получается, что самое массовое использование Linux в мире не полагается на glibc, а значит и не вкладывается в его развитие. glibc как бы остаётся в стороне от прогресса, и судя по всему для этого есть вполне резонные основания. И дело тут не только в проблемах с лицензией. Качество кода оставляет желать лучшего.

Так что напрашивается мысль: не пора ли переводить основные дистрибутивы на использование альтернатив (той же libmusl, например)?

Прошу учесть, что написанное является конечно во многом моим оценочным суждением. Но на код вы можете посмотреть сами.

Теги:
Хабы:
Всего голосов 41: ↑30 и ↓11+33
Комментарии162

Публикации

Работа

QT разработчик
7 вакансий
Программист C++
93 вакансии

Ближайшие события