Какие сигналы существуют в операционной системе
Что проверяют
Понимаете ли вы, как процесс получает команды от ОС и оркестратора, и умеете ли корректно останавливать Go-сервис. Почти всегда следом просят написать graceful shutdown или объяснить, почему сервис в контейнере не реагирует на docker stop.
Как отвечать
Сигнал это асинхронное уведомление процессу от ядра или другого процесса. У каждого есть действие по умолчанию: завершить, завершить с core dump, остановить или проигнорировать. Основные:
SIGINT: прерывание,Ctrl+Cв терминале;SIGTERM: просьба завершиться. Его шлётkillпо умолчанию,docker stopи Kubernetes перед удалением пода, а черезterminationGracePeriodSeconds, по умолчанию 30 секунд, придётSIGKILL;SIGKILLиSIGSTOP: перехватить или проигнорировать нельзя, процесс не успеет ничего дописать;SIGHUP: исторически обрыв терминала, по соглашению им просят перечитать конфиг;SIGQUIT:Ctrl+\. Go по умолчанию печатает стеки горутин и выходит, удобно при отладке зависания;SIGUSR1,SIGUSR2: смысл назначает само приложение;SIGSEGV,SIGBUS,SIGFPE: синхронные, от ошибки в самом коде. Go превращает их в панику.
Обработчиков в стиле C в Go нет, сигналы приходят в канал через пакет os/signal: signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) или удобнее signal.NotifyContext, который отменяет контекст. Дальше сервис перестаёт принимать запросы, вызывает srv.Shutdown(ctx) с таймаутом, дожидается воркеров и закрывает соединения с базой. Плюсом будет знать, что рантайм сам занимает SIGURG для вытеснения горутин.
Где спотыкаются
Передают в signal.Notify небуферизованный канал. Пакет не блокируется на отправке, и сигнал, пришедший в неудачный момент, теряется, поэтому нужен буфер хотя бы на один.
Пытаются поймать SIGKILL или os.Kill. Это не работает, и логика «допишем данные перед смертью» должна жить в обработке SIGTERM.
Забывают про контейнер. Сервис запускают через скрипт-обёртку или shell-форму CMD, и первым процессом становится оболочка, которая сигнал дальше не передаёт. docker stop ждёт 10 секунд и убивает контейнер жёстко. Лечится exec-формой или exec в скрипте.