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 3O que acontece no sinal#
| Passo | Por quê |
|---|---|
encerrando() passa a yes | um 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 registro | quem 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 outros | fechar o banco não pode depender de o log ter fechado |
sai com 128 + sinal — 143 para SIGTERM | o código que o orquestrador espera de uma saída por sinal |
| um segundo sinal sai na hora | quem 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.