Pular para o conteúdo

Encerrar em ordem

SIGTERM, SIGINT e SIGHUP rodam os finalizadores ao contrário, e o processo sai com 128 + sinal.

O docker stop, o Kubernetes e o systemctl stop pedem para o processo terminar mandando SIGTERM. Um programa que não trata o sinal morre na hora: a transação no meio não confirma, o arquivo não fecha, a mensagem pega da fila não é devolvida. Inicio.ao_encerrar registra o que precisa rodar antes de sair.

dataforge
adopt Arcane.Inicio as Inicio

log := []
Inicio.ao_encerrar(lambda => log.append("banco fechado"))
Inicio.ao_encerrar(lambda => log.append("fila devolvida"))

// o laço de trabalho confere a cada volta
atendidos := 0
persist not Inicio.encerrando() and atendidos smaller 3:
    atendidos += 1
assert atendidos is 3

O que acontece no sinal#

PassoPor quê
encerrando() passa a yesum laço que confere para por conta própria, no fim da volta — sem cortar um pedido no meio
os finalizadores rodam ao contrário do registroquem abriu por último fecha primeiro, como uma pilha de defer: a fila, que usa o banco, fecha antes dele
um finalizador que falha não impede os outrosfechar o banco não pode depender de o log ter fechado
sai com 128 + sinal — 143 para SIGTERMo código que o orquestrador espera de uma saída por sinal
um segundo sinal sai na horaquem aperta Ctrl+C duas vezes não quer esperar

O fim normal do programa também roda os finalizadores, uma vez só — registrar para o sinal e esquecer do fim comum era o defeito de metade dos atexit escritos à mão.