Обработка сигналов при подключении к разъему - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь обработать получение сигналов в моем скрипте 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(), как только сигнал получен?

...