Nenhum SIGTERM antes do SIGKILL/desligamento com systemd no Ubuntu 16.04

Nenhum SIGTERM antes do SIGKILL/desligamento com systemd no Ubuntu 16.04

Eu me deparei com esse problema enquanto tentavaresponda uma pergunta no Stackoverflow.

Ao desligar, o Ubuntu 12.04 envia SIGTERMpara 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.txtno diretório atual para todas as saídas. Possui um loop que imprime 'running' a cada segundo. O recebimento SIGTERMinterrompe 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 SIGHUPou tratar SIGTERMda SIGHUPmesma 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)

informação relacionada