2

Below is my test code.
When running with python2.7 it shows that the program won't receive any signal until all spawned threads finish.
While with python3.2, only the main thread's sigintHandler gets called.
I'am confused with how python handles threads and signal, so how do I spawn a thread and do signal handling within that thread? Is it possible at all?

from __future__ import print_function
from threading import Thread
import signal, os, sys
from time import sleep

def sigintHandler(signo, _):
    print("signal %d caught"%signo)

def fn():
    print("thread sleeping")
    sleep(10)
    print("thread awakes")

signal.signal(signal.SIGINT, sigintHandler)

ls = []
for i in range(5):
    t = Thread(target=fn)
    ls.append(t)
    t.start()

print("All threads up, pid=%d"%os.getpid())
for i in ls:
    i.join()

while True:
    sleep(20)
adamsmith
  • 5,759
  • 4
  • 27
  • 39

2 Answers2

0

You said: While with python3.2, only the main thread's sigintHandler gets called.

I think it is right. From here:Signals and threads

Python signal handlers are always executed in the main Python thread, even if the signal was received in another thread. This means that signals can’t be used as a means of inter-thread communication. You can use the synchronization primitives from the threading module instead.

Besides, only the main thread is allowed to set a new signal handler.

BlackMamba
  • 10,054
  • 7
  • 44
  • 67
0

Python doesn't handle signals asynchronously. When you install a signal handler in python, the runtime installs a C signal handler stub that just sets a flag. The interpreter checks the flag between bytecode instructions and then invokes the python signal handler. That means that signals handlers can only run between bytecode operations. If the main python thread is executing C code, it won't be able to handle signals until the current operation completes. There is some provision for SIGINT (i.e., control-C) to abort blocked IO, but only in the main thread.

That said, if you want to execute code in a thread based on receipt of a signal, the way to do it is to receive the signal in the main thread then send a message to the worker thread via a Queue. You will have to make sure that your main thread never blocks in a non-interruptible call. In python 2.7, join is not interuptable (as you have discovered). In later versions of python it is.

Evan
  • 2,217
  • 15
  • 18