简体   繁体   中英

Trapping and handling taskkill in Windows Python

I am using Python 2.6.6 for Windows (on Windows XP SP3) with pywin32-218.

In my Python application, I have a second thread (apart from the main thread) which spawns a subprocess to run another Windows executable.

My problem is that when the main process (python.exe) is killed (eg using taskkill), I want to terminate the subprocess (calc.exe) and perform some cleaning up.

I tried various methods (atexit, signal and win32api.handleConsoleCtrl), but none seem to be able to trap the taskkill signal.

My code as follows (test.py):

import sys
import os
import signal
import win32api
import atexit
import time
import threading
import subprocess

class SecondThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.secondProcess = None
    def run(self):
        secondCommand = ['C:\WINDOWS\system32\calc.exe']
        self.secondProcess = subprocess.Popen(secondCommand)
        print 'calc.exe running'
        self.secondProcess.wait()
        print 'calc.exe stopped'
        # do cleanup here
    def stop(self):
        if self.secondProcess and self.secondProcess.returncode == None:
            self.secondProcess.kill()

secondThread = SecondThread()

def main():
    secondThread.start()

def cleanup():
    print 'cleaning up'
    secondThread.stop()
    print 'cleaned up'

atexit.register(cleanup)

def handleSignal(signalNum, frame):
    print 'handleSignal'
    cleanup()
    sys.exit(0)

for signalNum in (signal.SIGINT, signal.SIGILL, signal.SIGABRT, signal.SIGFPE, signal.SIGSEGV, signal.SIGTERM):
    signal.signal(signalNum, handleSignal)

def handleConsoleCtrl(signalNum):
    print ('handleConsoleCtrl')
    cleanup()

win32api.SetConsoleCtrlHandler(handleConsoleCtrl, True)

main()

The application is launched using

python.exe test.py

The console then prints "calc.exe running", and the Calculator application runs, and using Process Explorer, I can see calc.exe as a sub-process of python.exe

Then I kill the main process using

taskkill /pid XXXX /f

(where XXXX is the PID for python.exe)

What happens after this is that the command prompt returns without further output (ie none of "cleaning up", "handleSignal" or "handleConsoleCtrl" gets printed), the Calculator application continues running, and from Process Explorer, python.exe is no longer running but calc.exe has re-parented itself.

Taskkill (normally) sends WM_CLOSE . If your application is console only and has no window, while you can get CTRL_CLOSE_EVENT via a handler set by SetConsoleCtrlHandler (which happens if your controlling terminal window is closed) you can't receive a bare WM_CLOSE message.

If you have to stick with taskkill (rather than using a different program to send a Ctrl-C ) one solution is to set the aforementioned handler and ensure your application has its own terminal window (eg by using start.exe "" <yourprog> to invoke it). See https://stackoverflow.com/a/23197789/4513656 for details an alternatives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM