在多级线程中没有调用Python信号处理程序(两个级别)

时间:2014-03-07 06:45:48

标签: python-2.7 signals python-multithreading

当我使用多级/嵌套(线程级别2)线程时,不会调用Python信号处理程序。不确定究竟是什么导致了这一点。相关代码如下。

作为多级/嵌套线程的替代方法,我可以尝试使用多进程+线程或队列+线程。但我真的想知道这个问题的原因或任何解决方案。好像它与python Global Interpreter Lock(GIL)有关。

在python中处理多级线程应用程序信号的最佳方法是什么?

CODE

#!/usr/bin/python

import threading, sys
import signal, time

threads = []
threadsL1 = []
threadsL1_statusflag = False
stopExecutionFlag = False


class MyThread(threading.Thread):
    global stopExecutionFlag
    def __init__(self, name):
    super(MyThread, self).__init__()
        self._tname = name
    self._terminate = False

    #threading.Thread.__init__(self)

    def terminate(self):
    print "L2[%s] : calling terminate" % self._tname
    self._terminate = True
    stopExecutionFlag = True

    def run(self):
    print "L2[%s]: Running" % self._tname
    while True:
        if stopExecutionFlag: 
        print "L2[%s] : stopExecutionFlag is set. Exiting now !!"
        break
        print "L2[%s]: Sleeping for 2 sec" % self._tname
        time.sleep(2)

    print "L2[%s]: Thread stopped" % self._tname


def startThreadL2(name):
    global threads
    print "L1[%s] Inside startThreadL2" % name
    t1 = MyThread(name)
    t1.start()
    threads.append(t1)
    print "L2[%s] Thread started and appended to threads array" % name

def joinThreadsL2():
    global threads
    print "L2 Inside joinThreadsL2()"
    for thread in threads:
    thread.join()    
    print "All threads finished execution"

def stopThreadsL2():
    global stopExecutionFlag
    stopExecutionFlag = True

    print "Inside stopThreadsL2()"
    joinThreadsL2()

def startThreadL1_and_wait():
    global threadsL1
    print "Main() calling startThreadL1()"
    for i in range(1,3):
    t1 =  threading.Thread(target=startThreadL2, args=("T%d" % i,))
    t1.start()
    threadsL1.append(t1)
    print "L1[%s] : Thread started" % ("T%d" % i)

    print "L1[%s] : Waiting for all threads to finish"
    for t2 in threadsL1:
    t2.join()
    print "L1[%s] : All L1 threads finished"
    threadsL1_statusflag = True

def stopThreadsL1():
    global threadsL1_statusflag
    if not threadsL1_statusflag:
    print "L1[%s] : Waiting for all threads to finish"
    for t2 in threadsL1:
        t2.join()
    print "L1[%s] : All L1 threads finished" 
        threadsL1_statusflag = True

def terminate(signum, frame):
    print "\n------------------------------ Inside terminate()-------------------------\n\n"
    stopThreadsL2()
    stopThreadsL1()
    sys.exit(1)

def main():
    m_threads = []

    signal.signal(signal.SIGINT, terminate)
    signal.signal(signal.SIGTERM, terminate)

    print "\n-----------------------Inside main thread------------------------\n"
    startThreadL1_and_wait()

    print "\n------------------------- All L1 threads started. Press Ctrl+C to stop !!------------------------\n"
    joinThreadsL2() 



if __name__ == '__main__':
    main()



输出

<pre>
reynold@heuristics:~/test$ python test_threading.py 

    -----------------------Inside main thread------------------------

    Main() calling startThreadL1()
    L1[T1] Inside startThreadL2
     L1[T1] : Thread started
    L2[T1]: Running
     L2[T1] Thread started and appended to threads array
    L2[T1]: Sleeping for 2 sec
    L1[T2] Inside startThreadL2
     L2[T2]: Running
     L2[T2]: Sleeping for 2 sec
    L2[T2] Thread started and appended to threads array
    L1[T2] : Thread started
    L1[%s] : Waiting for all threads to finish
    L1[%s] : All L1 threads finished

    ------------------------- All L1 threads started. Press Ctrl+C to stop !!------------------------

    L2 Inside joinThreadsL2()
    L2[T2]: Sleeping for 2 sec
     L2[T1]: Sleeping for 2 sec
    L2[T2]: Sleeping for 2 sec
    L2[T1]: Sleeping for 2 sec
    L2[T2]: Sleeping for 2 sec
    L2[T1]: Sleeping for 2 sec
    ^CL2[T2]: Sleeping for 2 sec
    L2[T1]: Sleeping for 2 sec
    ^CL2[T2]: Sleeping for 2 sec
    L2[T1]: Sleeping for 2 sec
    ^C^C^C^C^C^C^C^CL2[T2]: Sleeping for 2 sec
    L2[T1]: Sleeping for 2 sec
    ^C^Z
    [1]+  Stopped                 python test_threading.py
    reynold@heuristics:~/test$ kill -9 %1

    [1]+  Stopped                 python test_threading.py
    reynold@heuristics:~/test$ 
</pre>

1 个答案:

答案 0 :(得分:-1)

我在3.6中遇到了完全相同的问题,发现的解决方案是先在main中设置SIG_IGN,然后在创建线程之后,设置您自己的处理程序。

signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
worker.start()
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)

这确实是一个奇怪的问题,调用顶层类(直接继承线程)不会中断信号,但是任何较低层的类都需要解决方法。