Найти в Дзене
Alex Chernyshev

snapd, загрузка cpu и баг ядра

Оглавление

Еще одна поучительная история из жизни Linux, чтобы вы потеряли сон и покой, узнав что такое вообще возможно.

Тот самый баг
Тот самый баг

Вводная

Эмм с чего бы такого начать, чтобы вы не обосрались раньше времени от прочитанного и не побежали устанавливать *BSD.

Есть на свете одна компания, которой мы помогаем с ИТ, у нее было несколько виртуальных серверов на Ubuntu Linux, используемых в основном для разработки и тестов.

Ubuntu там использовалась нормальной LTS-версии, но в какой-то момент в погоне за патчами безопасности ее обновили до текущей.

Все происходило летом 2025 года, поэтому речь про 25.04 версию Ubuntu, которая использует ядро 6.14 — запомните этот момент:

-2

Баг

Однажды админ компании заметил слишком частую и сильную нагрузку на CPU, создаваемую процессом snapd, отвечающим за подсистему установки и обновления пакетов Snap.

Скриншот не мой, поэтому шакальего качества ;)
Скриншот не мой, поэтому шакальего качества ;)

Проблема мягко говоря не нова — «проклятый snapd» гадил линуксоидам с момента своего появления на свет и вообще видимо был придуман в качестве «кары за грехи».

Но в этот раз загрузка CPU происходила.. строго по расписанию:

-4

Разумеется первым делом были опробованы стандартные решения, вроде снижения частоты проверок обновлений или полного отключения сервиса:

-5

Особо порадовала выдача ответа ИИ по данной проблеме:

-6

Т.е. дословно «снести к х#ям и использовать что-то другое» — можно сказать первый разумный совет от машины за всю историю искусственного интеллекта!

Дальнейшие изыскания привели в багтрекер snapd к упомянутому багу, где третий же комментарий от разработчика snapd, с приложенной трассировкой вызовов показал что проблема именно в ядре:

-7

Тут стоит добавить, что встал вопрос проверки этого бага на локальной машине, поскольку на момент изучения вопроса все успело обновиться, а отлаживать ядро Linux на сервере заказчика все же не очень хорошая затея.

Чуть ниже по переписке видно что баг особо ярко проявляется на ноутбуке, работающем от батареи:

-8

Так что решено было пробовать отловить именно в таких условиях.

На счастье, на машине осталась сборка 6.14 версии ядра с патчами от Xanmod, которая использовалась для статьи про l9ec.

В последние годы у Linux выпускается очень много промежуточных релизов, поэтому на какой именно версии внутри 6.14 ветки что-то пошло не так еще пришлось выяснять:

-9

Наконец источник проблем был найден:

-10

Чуть ниже по переписке обнаружился и тестовый код на 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);
}

А так это выглядит в действии:

-11

Вот так, в очередной раз проблема чисто прикладного сервиса уперлась кривыми рогами в ядро ОС.

Патч находится тут, само место исправления выглядит вот так:

-12

Да, как видите это еще один случай когда ситуацию радикально исправляет буквально пара символов логической конструкции.

Текущее состояние

Формально проблема была решена еще летом, патч попал в mainline и пакет с обновлением ядра от команды Ubuntu:

-13

На осень 2025 года даже стабильная версия ядра Linux уже имеет верси 6.16 — т. е. паровоз разработки уехал уже очень далеко от описываемых проблем:

-14

Так что по идее на момент написания данной статьи, вы не должны столкнуться с данной проблемой, а если столкнетесь — все решается банальным обновлением версии ядра из пакетов дистрибутива.

Но если есть подозрение, что источник проблем именно в данном баге — попробуйте собрать тестовое приложение (см. выше) и запустить в своем окружении.

Если начнется загрузка CPU запущенным процессом — проблема точно есть, поскольку в ядрах с патчем поведение тестового приложения отличается:

-15

Как можно заметить тут не происходит блокировки и приложение немедленно завершается.

Что касается нашей компании-заказчика, то поскольку патч был опубликован довольно быстро — мы на время разборок с согласованиями попадания в mainline банальным образом перенесли патч вручную в версию ядра, которая использовалась на сервере.