Нет SIGTERM перед SIGKILL/выключением с помощью systemd в Ubuntu 16.04

Нет SIGTERM перед SIGKILL/выключением с помощью systemd в Ubuntu 16.04

Я столкнулся с этой проблемой, когда пыталсяответить на вопрос на Stackoverflow.

При завершении работы Ubuntu 12.04 отправляет SIGTERMвсем процессам и ждет максимум 10 секунд, прежде чем завершить их с помощью SIGKILL(если они не были завершены раньше). Мой ответ на SO даже содержит скрипт Python, который проверяет это поведение. Скрипт запускается в терминале, отправляется в фоновый режим, а затем терминал отрекается от него. При получении SIGTERMскрипт просто продолжает работать и непрерывно выводит в файл, как долго он работаетпослеполучение SIGTERM.

Однако в Ubuntu 16.04 скрипт немедленно завершается при завершении работы (сообщение не SIGTERMрегистрируется).

Я гуглил некоторое время, но ничего полезного не нашел. Неужели никто не сталкивался с этим критическим изменением для текущего релиза LTS?

Вот сценарий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)

Скрипт использует файл log.txtв текущем каталоге для всех выходных данных. Он имеет цикл, который печатает «running» каждую секунду. Получение SIGTERMпрерывает цикл и запускает другой цикл, который печатает секунды, прошедшие с момента получения SIGTERM.

Скрипт запускается из терминала и отсоединен с помощью disown:

python signaltest.py &
disown

Просто быть чистым:Это не дубликатUbuntu не отправляет SIGTERM при завершении работы. Вопрос касается настольных приложений, и ответы тоже не подходят.

решение1

systemd (в отличие от upstart в более ранних версиях Ubuntu) дополнительно отправляет SIGHUP при завершении работы (и ждет 90 с вместо 10 с перед отправкой SIGKILL). Я предлагаю игнорировать SIGHUPили обрабатывать SIGTERMи SIGHUPтем же (идемпотентным) способом.

Модифицированный тестовый сценарий можно изменить следующим образом:

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)

Связанный контент