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_EVENTandsignal.CTRL_BREAK_EVENTsignals are special signals which can only be sent to console processes which share a common console window, e.g., some subprocesses. Any other value forsigwill cause the process to be unconditionally killed by theTerminateProcessAPI, 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