Não SIGTERM antes de SIGKILL / shutdown com systemd no Ubuntu 16.04

1

Eu encontrei esse problema enquanto tentava responder a uma pergunta no Stackoverflow .

No desligamento, o Ubuntu 12.04 envia SIGTERM para todos os processos e aguarda no máximo 10 segundos antes de eliminá-los com SIGKILL (a menos que tenham terminado antes). Minha resposta em SO ainda contém um script Python que verifica esse comportamento. O script é iniciado em um terminal, enviado para o segundo plano e deserdado pelo terminal. Ao receber SIGTERM , o script simplesmente continua e imprime continuamente em um arquivo por quanto tempo ele está sendo executado após receber SIGTERM .

Ubuntu 16.04 no entanto, o script é morto imediatamente após o desligamento (não há SIGTERM registrado).

Eu pesquisei por um tempo, mas não consegui encontrar nada de útil. Ninguém nunca se deparou com essa mudança de quebra para o lançamento atual do LTS?

Aqui está o script signaltest.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. Tem um loop que imprime "correndo" a cada segundo. Receber SIGTERM interrompe o loop e inicia outro loop que imprime os segundos decorridos desde o recebimento de SIGTERM .

O script é executado a partir de um terminal que é separado usando disown :

python signaltest.py &
disown

Só para deixar claro: Esta não é uma duplicata de O Ubuntu não está enviando o SIGTERM no desligamento . A questão é sobre aplicativos de desktop e as respostas também não se encaixam.

    
por code_onkel 01.09.2016 / 21:21

1 resposta

3
O

systemd (oposto ao upstart em versões anteriores do Ubuntu) também envia SIGHUP no desligamento (e aguarda 90s em vez de 10s antes de enviar SIGKILL ). Sugiro ignorar SIGHUP ou manipular SIGTERM e SIGHUP da 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)
    
por code_onkel 01.09.2016 / 23:12