Python SIGINT не перехвачен

Мне не удается понять, почему мой SIGINT никогда не перехватывается фрагментом кода ниже.

#!/usr/bin/env python
from threading import Thread
from time import sleep
import signal

class MyThread(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.running = True

    def stop(self):
        self.running = False

    def run(self):
        while self.running:
            for i in range(500):
                col = i**i
                print col
                sleep(0.01)

global threads
threads = []

for w in range(150):
    threads.append(MyThread())

def stop(s, f):
    for t in threads:
        t.stop()

signal.signal(signal.SIGINT, stop)

for t in threads:
    t.start()

for t in threads:
    t.join()

Чтобы очистить этот код, я бы предпочел попробовать/исключить соединение () и закрыть все потоки в случае исключения, это сработает?


person myoan    schedule 15.04.2015    source источник
comment
Возможный дубликат прерываемого объединения потоков в Python   -  person Trevor Boyd Smith    schedule 27.11.2017


Ответы (1)


Одна из проблем с многопоточностью в python заключается в том, что join() более или менее отключает сигналы.

Это связано с тем, что сигнал может быть доставлен только в основной поток, но основной поток уже занят выполнением join() и соединение не может быть прервано.

Вы можете сделать вывод из документации модуля signal

Следует проявлять некоторую осторожность, если в одной и той же программе используются и сигналы, и потоки. Фундаментальная вещь, которую следует помнить при одновременном использовании сигналов и потоков: всегда выполняйте операции signal() в основном потоке выполнения. Любой поток может выполнять функции alarm(), getsignal(), pause(), setitimer() или gettimer(); только основной поток может установить новый обработчик сигналов, и основной поток будет единственным, кто будет получать сигналы (это обеспечивается сигнальным модулем Python, даже если базовая реализация потока поддерживает отправку сигналов в отдельные нити). Это означает, что сигналы нельзя использовать в качестве средства межпоточной связи. Вместо этого используйте замки.

Вы можете обойти это, зациклив операцию соединения:

for t in threads:
    while t.isAlive():
        t.join(timeout=1)

Это, однако, неэффективно:

Обходной путь вызова join() с тайм-аутом имеет недостаток: процедура ожидания многопоточности Python опрашивает 20 раз в секунду при любом тайм-ауте. Весь этот опрос может означать множество прерываний/пробуждения процессора на бездействующем ноутбуке и быстрее разряжать аккумулятор.

Некоторые подробности приведены здесь:

Программа Python с потоком не может поймать CTRL+C

Отчеты об ошибках для этой проблемы с обсуждением основной проблемы можно найти здесь:

https://bugs.python.org/issue1167930

https://bugs.python.org/issue1171023

person dhke    schedule 15.04.2015