subprocess: deleting child processes in Windows subprocess: deleting child processes in Windows python python

subprocess: deleting child processes in Windows


By using psutil:

import psutil, osdef kill_proc_tree(pid, including_parent=True):        parent = psutil.Process(pid)    children = parent.children(recursive=True)    for child in children:        child.kill()    gone, still_alive = psutil.wait_procs(children, timeout=5)    if including_parent:        parent.kill()        parent.wait(5)me = os.getpid()kill_proc_tree(me)


Use taskkill with the /T flag

p = subprocess.Popen(...)<wait>subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)])

The flags to taskkill has the following docs:

TASKKILL [/S system [/U username [/P [password]]]]         { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]/S    system           Specifies the remote system to connect to./U    [domain\]user    Specifies the user context under which the                       command should execute./P    [password]       Specifies the password for the given user                       context. Prompts for input if omitted./FI   filter           Applies a filter to select a set of tasks.                       Allows "*" to be used. ex. imagename eq acme*/PID  processid        Specifies the PID of the process to be terminated.                       Use TaskList to get the PID./IM   imagename        Specifies the image name of the process                       to be terminated. Wildcard '*' can be used                       to specify all tasks or image names./T                     Terminates the specified process and any                       child processes which were started by it./F                     Specifies to forcefully terminate the process(es)./?                     Displays this help message.

Or walk the process tree using comtypes and win32api:

def killsubprocesses(parent_pid):    '''kill parent and all subprocess using COM/WMI and the win32api'''    log = logging.getLogger('killprocesses')    try:        import comtypes.client    except ImportError:        log.debug("comtypes not present, not killing subprocesses")        return    logging.getLogger('comtypes').setLevel(logging.INFO)    log.debug('Querying process tree...')    # get pid and subprocess pids for all alive processes    WMI = comtypes.client.CoGetObject('winmgmts:')    processes = WMI.InstancesOf('Win32_Process')    subprocess_pids = {} # parent pid -> list of child pids    for process in processes:        pid = process.Properties_('ProcessID').Value        parent = process.Properties_('ParentProcessId').Value        log.trace("process %i's parent is: %s" % (pid, parent))        subprocess_pids.setdefault(parent, []).append(pid)        subprocess_pids.setdefault(pid, [])    # find which we need to kill    log.debug('Determining subprocesses for pid %i...' % parent_pid)    processes_to_kill = []    parent_processes = [parent_pid]    while parent_processes:        current_pid = parent_processes.pop()        subps = subprocess_pids[current_pid]        log.debug("process %i children are: %s" % (current_pid, subps))        parent_processes.extend(subps)        processes_to_kill.extend(subps)    # kill the subprocess tree    if processes_to_kill:        log.info('Process pid %i spawned %i subprocesses, terminating them...' %             (parent_pid, len(processes_to_kill)))    else:        log.debug('Process pid %i had no subprocesses.' % parent_pid)    import ctypes    kernel32 = ctypes.windll.kernel32    for pid in processes_to_kill:        hProcess = kernel32.OpenProcess(PROCESS_TERMINATE, FALSE, pid)        if not hProcess:            log.warning('Unable to open process pid %i for termination' % pid)        else:            log.debug('Terminating pid %i' % pid)                                    kernel32.TerminateProcess(hProcess, 3)            kernel32.CloseHandle(hProcess)


Here's example code for the Job object method, but instead of subprocess it uses win32api.CreateProcess

import win32processimport win32jobstartup = win32process.STARTUPINFO()(hProcess, hThread, processId, threadId) = win32process.CreateProcess(None, command, None, None, True, win32process.CREATE_BREAKAWAY_FROM_JOB, None, None, startup)hJob = win32job.CreateJobObject(None, '')extended_info = win32job.QueryInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation)extended_info['BasicLimitInformation']['LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEwin32job.SetInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation, extended_info)win32job.AssignProcessToJobObject(hJob, hProcess)