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
It's not working because you can't use os.kill
to send arbitrary signals on Windows:
os.kill(pid, sig)
Send signal sig to the process pid. Constants for the specific signals available on the host platform are defined in the signal module.
Windows: The
signal.CTRL_C_EVENT
andsignal.CTRL_BREAK_EVENT
signals are special signals which can only be sent to console processes which share a common console window, e.g., some subprocesses. Any other value forsig
will cause the process to be unconditionally killed by theTerminateProcess
API, and the exit code will be set to sig. The Windows version ofkill()
additionally takes process handles to be killed.
The only signals that can be sent via os.kill
are signal.CTRL_C_EVENT
and signal.CTRL_BREAK_EVENT
. Anything else just terminates the process, which is what is happening in your case. Using signal.CTRL_C_EVENT
won't work here, either, because processes started via multiprocessing.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 catch TerminateProcess
the way you can catch SIGTERM
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, so signal.*_EVENT
won't work.
I think your options are: 1) Use the subprocess
module, and launch the child process with shell=True
, which I believe will mean signal.CTRL+C+EVENT
will work. 2) Stick with the multiprocessing
module, and use a "co-operative" method of interrupting the worker, like multiprocessing.Event
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With