Вопрос

I wrote a little script that does something extremely time-consuming in Python and I included a signal handling module that listens for SIGINT, SIGQUIT and SIGINFO, printing the status when either SIGQUIT or SIGINFO are inputted by the user and aborting the program when SIGINT(CTRL-C) is entered. The code is EXTREMELY sloppy, because i hacked it down in a few minutes and stole some foreign code - dont worry, ill clean it up as soon as I(or rather, you, because I'm stuck) found the bug:

def setup_signals(progress_bar):
import signal
import sys

def progress(*args):
    print(progress_bar)

def killitwithfire(*args):
    print("[x] User interrupted with CTRL-C. Aborting.")
    sys.exit(0)

for sig in (signal.SIGINFO, signal.SIGQUIT):
    signal.signal(sig, progress)
for sig in (signal.SIGINT,):
    signal.signal(sig, killitwithfire)
print("Sig handlers built:\n Press Ctrl+T(BSD/OS X) or Ctrf+4(Linux) for progress.")
print("Press CTRL-C to abort.")

Now, the problem is that when CTRL-C is entered, the message in killitwithfire() - sorry for the bad reference - is printed, but it won't exit.

The code in which this is executed is inside a try/catch/ block. If that is the problem, how can I exit from within this signal handling module? If it is not the problem, then what is it?

Это было полезно?

Решение

Signal handling is not done in the main thread, so calling sys.exit() won't do the trick of stopping the main thread. Actually, calling this will only raise a special internal exception (SystemExit) which will terminate the current thread, if uncaught. There is no python-internal standard way of signaling one thread to please terminate, so ending the signal-handling thread won't terminate the main thread.

You have several options.

One is to check inside the longrunner thread for a certain condition (global variable or threading.Condition or similar), and if this states to "please terminate", then stop looping.

Another is to use the operating system's facilities and kill your process with all its threads (e. g. by sending a signal you don't catch, e. g. SIGKILL, to yourself).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top