TGViewer
About Python [ru] About Python [ru] @python_tesst · 6.45K subscribers
Post #2813 321
⁣Graceful Shutdown в asyncio: как не потерять данные при SIGTERM в production

Стандартный signal.signal блокирует event loop, превращая асинхронное приложение в синхронный ступор. Решение - loop.add_signal_handler(), но без pipe вы рискуете утечкой ресурсов: воркеры не успеют закрыть соединения или снять блокировки.

Проблема: почему просто cancel() не работает
Сигналы обрабатываются в том же потоке, что и цикл событий. Если в обработчике сразу отменять корутины, вы получите состояние гонки: одни задачи завершатся, другие - нет. Ресурсы утекут, соединения повиснут. Пример частой ошибки:
def handler():
for task in asyncio.all_tasks():
task.cancel() # Блокировка в синхронном контексте


Решение: pipe как мост между синхронным и асинхронным миром
Используйте os.pipe() для безусловного пробуждения цикла. Обработчик сигнала только пишет байт в pipe - никаких корутин или блокировок. Через add_reader асинхронный контекст подхватывает запись и выполняет graceful shutdown:
class GracefulShutdown:
def __init__(self):
self.loop = asyncio.get_event_loop()
self.r_fd, self.w_fd = os.pipe()
self.loop.add_reader(self.r_fd, self._handle_stop)
for sig in (signal.SIGTERM, signal.SIGINT):
self.loop.add_signal_handler(sig, self._signal_handler)

def _signal_handler(self):
os.write(self.w_fd, b'\x00') # Только запись


Критичное правило: никакой логики в _signal_handler
Запись в pipe - единственная операция. Закрытие дескрипторов, отмена задач, asyncio.all_tasks() - все это делается в асинхронном _handle_stop, где task.cancel() пробрасывает CancelledError в воркеры, давая шанс выполнить cleanup. Если нарушить это правило в многопоточном run_in_executor, словите блокировку цикла.

Trade-off: pipe vs call_soon_threadsafe
loop.call_soon_threadsafe тоже работает, но pipe надежнее в сценариях с воркерами в других потоках: он гарантированно будит именно тот цикл, который слушает. Без pipe вы рискуете, что сигнал пропустит цикл, занятый долгим await.

Вывод: Pipe + add_signal_handler превращает SIGTERM из источника утечек в управляемое завершение, где каждый воркер закрывает ресурсы через CancelledError.
More from @python_tesst
  1. Sep 28, 2026Post #3191
  2. Sep 27, 2026OpenAI метит в подписку за 500 баксов Что там в описании тарифа? Пока что от ChatGPT Pro о…
  3. Sep 27, 2026Post #3189
  4. Sep 27, 2026Свежая обложка The Economist подъехала Журналисты: да мы вообще не сгущаем краски Те же жу…
  5. Sep 27, 2026Ночная годнота: Docker выкатила первые официальные скиллы для ИИ-агентов, которые ковыряют…
  6. Sep 27, 2026Post #3186
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →