Я пытаюсь обработать получение сигналов в моем скрипте Python для очистки и корректного выхода.В сценарии используется множество socket
соединений, которые, как я понял, могут быть запущены во время получения сигнала, и что мне нужно было это исследовать.В частности, ожидание ответа сети немедленно прервалось бы, чтобы программа могла своевременно реагировать на сигнал.
К счастью, насколько мне показало мое исследование, кажется, что если сигналпроисходит во время любого системного вызова, например, в пределах socket.connect()
, он прерывается для немедленного вызова обработчика сигнала.Кроме того, в Python кажется, что если обработчик сигнала вызывает исключение, это исключение распространяется из кода, выполняющего системный вызов.
Таким образом, я подготовил следующий код для проверки прерывания ожидания сетевого ответа в случае сигнала.Мы моделируем длительное ожидание / тайм-аут сети, пытаясь подключиться к Google через порт, на который он не отвечает.Во время этого ожидания сигнал выхода (CTRL_C_EVENT
, который обрабатывается SIGINT, потому что я в настоящее время использую Windows) генерируется асинхронно.Обработчик сигнала вызывается и вызывает SystemExit
исключение через sys.exit()
, которое затем должно быть выброшено из socket.connect()
и перехвачено, и программа завершается корректно.
import os
import signal
import socket
import sys
import threading
import time
def kill():
print("Raising signal at {}".format(time.time()))
os.kill(os.getpid(), signal.CTRL_C_EVENT)
def handler(signo, frame):
print("Handling signal at {}".format(time.time()))
sys.exit()
signal.signal(signal.SIGINT, handler)
t = threading.Timer(5, kill)
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10)
print("Connecting at {}".format(time.time()))
t.start()
s.connect(("www.google.com", 81))
print("Connected at {}".format(time.time()))
except SystemExit as e:
print("Caught SystemExit at {}".format(time.time()))
raise e
Я ожидаю, что программабудет выводить по линии:
Connecting at <some time A>
Raising signal at <~5s after A>
Handling signal at <~5s after A>
Caught SystemExit at <~5s after A>
<program exits>
Но пример того, что я на самом деле получаю, это:
Connecting at 1544985636.4006333
Raising signal at 1544985641.4017904
Handling signal at 1544985646.4649496
<program exits>
Как вы можете видеть, не только исключение SystemExit
магически исчезает где-то, но обработчик сигнала вызывается через 5 секунд после повышения сигнала!Похоже, что socket.connect
съедает сигнал, а затем истекает время ожидания, в отличие от немедленного прерывания (но по какой-то причине не возникает никаких исключений?).
В чем причина этого странного поведения?И как я могу получить предполагаемое поведение выхода socket.connect()
, как только сигнал получен?