Eu me deparei com esse problema enquanto tentavaresponda uma pergunta no Stackoverflow.
Ao desligar, o Ubuntu 12.04 envia SIGTERM
para todos os processos e espera no máximo 10 segundos antes de eliminá-los SIGKILL
(a menos que tenham terminado antes). Minha resposta no SO contém até um script Python que verifica esse comportamento. O script é iniciado em um terminal, enviado para segundo plano e então rejeitado pelo terminal. Ao receber SIGTERM
, o script continua e imprime continuamente em um arquivo há quanto tempo está em execuçãodepoisrecebendo SIGTERM
.
No entanto, no Ubuntu 16.04, o script é eliminado imediatamente no desligamento (não SIGTERM
é registrado).
Pesquisei um pouco no Google, mas não consegui encontrar nada útil. Ninguém nunca se deparou com essa mudança significativa na versão atual do LTS?
Aqui está o roteirosignaltest.py
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
signal.signal(signal.SIGTERM, stop)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)
O script usa o arquivo log.txt
no diretório atual para todas as saídas. Possui um loop que imprime 'running' a cada segundo. O recebimento SIGTERM
interrompe o loop e inicia outro loop que imprime os segundos decorridos desde o recebimento SIGTERM
.
O script é executado a partir de um terminal desanexado usando disown
:
python signaltest.py &
disown
Só para ficar claro:Esta não é uma duplicata deUbuntu não está enviando SIGTERM no desligamento. A pergunta é sobre aplicativos de desktop e as respostas também não cabem.
Responder1
systemd (oposto ao upstart nas versões anteriores do Ubuntu) também envia SIGHUP no desligamento (e espera 90s em vez de 10s antes de enviar SIGKILL
). Sugiro ignorar SIGHUP
ou tratar SIGTERM
da SIGHUP
mesma forma (idempotente).
O script de teste modificado pode ser alterado assim:
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
def ignore(sig, frsma):
out.write('ignoring signal %d\n' % sig)
out.flush()
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGHUP, ignore)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)