Using python 3.4 on windows.
I am trying to terminate a child processing simulating a person pressing Ctrl+C (Ctrl+D on linux).
I just added the handler to check if the signal was being handled at all. I used the idea from this question
The objective is to catch the KeyboardInterrupt (SIGINT), and release the resources. But it seems that the exception is not thrown if SIGINT doesnt come from the keyboard. That's why I created an handler, but the process doesnt seem to run the handler at all…
import multiprocessing
import time
import signal
import signal
import os
import sys
def handler(signal, frame):
print("handler!!!")
sys.exit(10)
def worker():
p = multiprocessing.current_process()
try:
signal.signal(signal.SIGINT,handler)
print("[PID:{}] acquiring resources".format(p.pid))
while(True):
#working...
time.sleep(0.5)
except (KeyboardInterrupt, SystemExit):
pass
finally:
print("[PID:{}] releasing resources".format(p.pid))
if __name__ == "__main__":
lst = []
for i in range(1):
p = multiprocessing.Process(target=worker)
p.start()
lst.append(p)
time.sleep(3)
for p in lst:
os.kill(p.pid,signal.SIGINT)
p.join()
print(p)
print(p.exitcode)
print("joined all processes")
Here is an example of the output:
C:\Users\Rui>python test.py
[PID:16524] acquiring resources
<Process(Process-1, stopped[2])>
2
joined all processes
- What am I doing wrong?
- Should I use subprocess module?
- What other approaches could I try to interrupt a process execution?
Best Answer
It's not working because you can't use
os.kill
to send arbitrary signals on Windows:The only signals that can be sent via
os.kill
aresignal.CTRL_C_EVENT
andsignal.CTRL_BREAK_EVENT
. Anything else just terminates the process, which is what is happening in your case. Usingsignal.CTRL_C_EVENT
won't work here, either, because processes started viamultiprocessing.Process
aren't "console processes which share a common console window" with the parent. I'm not sure there's much you can do here with signals on Windows; It doesn't look like you're allowed to catchTerminateProcess
the way you can catchSIGTERM
on Unix, so you can't do any clean up prior to the process terminating, and you're not using a console application for the child, sosignal.*_EVENT
won't work.I think your options are: 1) Use the
subprocess
module, and launch the child process withshell=True
, which I believe will meansignal.CTRL+C+EVENT
will work. 2) Stick with themultiprocessing
module, and use a "co-operative" method of interrupting the worker, likemultiprocessing.Event
.