snapd, загрузка cpu и баг ядра
Еще одна поучительная история из жизни 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 банальным образом перенесли патч вручную в версию ядра, которая использовалась на сервере.
Позже обновили уже штатными средствами дистрибутива до текущей актуальной версии.
Эпилог
Из этой статьи можно сделать сразу несколько интересных выводов:
1. Н#хуй Linux, даешь BSD
Шучу, разумеется неподготовленным пользователям в BSD-системы лучше не лезть, но задуматься (или хотя-бы просто знать) о реалиях использования Linux все же стоит.
2.Граница между прикладкой и системной разработкой весьма абстрактна
Проще говоря — ее нет совсем, поэтому в любой произвольный момент времени у вас есть неиллюзорный шанс наткнуться на баг ядра, даже программируя на JavaScript в браузере.
3.Любой уважающий себя сисадмин и DevOps должен знать Си
Пусть на самом примитивном уровне, но хотя-бы собрать и запустить тестовое приложение он должен уметь. Плюс запуск трассировки и отладчика.
Все изыскания по теме «почему тормозит» или «почему упало» рано или поздно приводят к Си и отладчику ядра, чудес нет.
4.Считайте деньги
Описанная в статье проблема случилась в локализованном окружении (на собственных физических серверах компании), но точно такая же Ubuntu часто используется и облачными провайдерами вроде Amazon, где есть тарификация за использование ресурсов, в первую очередь CPU.
Как нетрудно догадаться, 100% загрузка процессора в облаке каждые пять минут если ее вовремя не заметить и не исправить — больно отразится на счете.
Так что проверяйте загруженность — пиковых 100% в современных реалиях быть не должно, если только вы целенаправленно не занимаетесь вычислительными задачами.