Еще одна поучительная история из жизни Linux, чтобы вы потеряли сон и покой, узнав что такое вообще возможно.
Вводная
Эмм с чего бы такого начать, чтобы вы не обосрались раньше времени от прочитанного и не побежали устанавливать *BSD.
Есть на свете одна компания, которой мы помогаем с ИТ, у нее было несколько виртуальных серверов на Ubuntu Linux, используемых в основном для разработки и тестов.
Ubuntu там использовалась нормальной LTS-версии, но в какой-то момент в погоне за патчами безопасности ее обновили до текущей.
Все происходило летом 2025 года, поэтому речь про 25.04 версию Ubuntu, которая использует ядро 6.14 — запомните этот момент:
Баг
Однажды админ компании заметил слишком частую и сильную нагрузку на CPU, создаваемую процессом snapd, отвечающим за подсистему установки и обновления пакетов Snap.
Проблема мягко говоря не нова — «проклятый snapd» гадил линуксоидам с момента своего появления на свет и вообще видимо был придуман в качестве «кары за грехи».
Но в этот раз загрузка CPU происходила.. строго по расписанию:
Разумеется первым делом были опробованы стандартные решения, вроде снижения частоты проверок обновлений или полного отключения сервиса:
Особо порадовала выдача ответа ИИ по данной проблеме:
Т.е. дословно «снести к х#ям и использовать что-то другое» — можно сказать первый разумный совет от машины за всю историю искусственного интеллекта!
Дальнейшие изыскания привели в багтрекер snapd к упомянутому багу, где третий же комментарий от разработчика snapd, с приложенной трассировкой вызовов показал что проблема именно в ядре:
Тут стоит добавить, что встал вопрос проверки этого бага на локальной машине, поскольку на момент изучения вопроса все успело обновиться, а отлаживать ядро Linux на сервере заказчика все же не очень хорошая затея.
Чуть ниже по переписке видно что баг особо ярко проявляется на ноутбуке, работающем от батареи:
Так что решено было пробовать отловить именно в таких условиях.
На счастье, на машине осталась сборка 6.14 версии ядра с патчами от Xanmod, которая использовалась для статьи про l9ec.
В последние годы у Linux выпускается очень много промежуточных релизов, поэтому на какой именно версии внутри 6.14 ветки что-то пошло не так еще пришлось выяснять:
Наконец источник проблем был найден:
Чуть ниже по переписке обнаружился и тестовый код на Cи, демонстрирующий проблему, вот такой:
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/wait.h>
int main() {
int e = epoll_create1(0);
struct epoll_event event = {.events = EPOLLIN};
epoll_ctl(e, EPOLL_CTL_ADD, 0, &event);
const struct timespec timeout = {.tv_nsec = 1};
epoll_pwait2(e, &event, 1, &timeout, 0);
}
А так это выглядит в действии:
Вот так, в очередной раз проблема чисто прикладного сервиса уперлась кривыми рогами в ядро ОС.
Патч находится тут, само место исправления выглядит вот так:
Да, как видите это еще один случай когда ситуацию радикально исправляет буквально пара символов логической конструкции.
Текущее состояние
Формально проблема была решена еще летом, патч попал в mainline и пакет с обновлением ядра от команды Ubuntu:
На осень 2025 года даже стабильная версия ядра Linux уже имеет верси 6.16 — т. е. паровоз разработки уехал уже очень далеко от описываемых проблем:
Так что по идее на момент написания данной статьи, вы не должны столкнуться с данной проблемой, а если столкнетесь — все решается банальным обновлением версии ядра из пакетов дистрибутива.
Но если есть подозрение, что источник проблем именно в данном баге — попробуйте собрать тестовое приложение (см. выше) и запустить в своем окружении.
Если начнется загрузка CPU запущенным процессом — проблема точно есть, поскольку в ядрах с патчем поведение тестового приложения отличается:
Как можно заметить тут не происходит блокировки и приложение немедленно завершается.
Что касается нашей компании-заказчика, то поскольку патч был опубликован довольно быстро — мы на время разборок с согласованиями попадания в mainline банальным образом перенесли патч вручную в версию ядра, которая использовалась на сервере.