1

I am using PSUTIL library(mainly because it's cross-platform) to kill a process and its descendants. But it's shutting down the process forcefully. I am using the '.terminate' command. I want to send a normal shutdown signal and kill a process gracefully. How can I do that?

def kill_process(self, pid, including_parent=True):

    '''
    Kill_process method will kill the process and it's descendants recursively
    '''
    err_msg_temp = None
    try:
        parent = psutil.Process(pid)
        for child in parent.children(recursive=False):
            child_pid = child.pid
            if child_pid not in deleted_processes:
                self.kill_process(child_pid)

        if including_parent:
            deleted_processes[pid] = 1
            parent.terminate()
    except Exception as e:
        err_msg_temp = str(e)

If there's a cross-platform command, I would like to know that as well.

  • 2
    There is not a cross-platform solution, but the proper way to gracefully end a process on Windows is to first send a WM_CLOSE message to the window, and then if the process is still running, on the second attempt call TerminateProcess which should be what parent.terminate is performing. This is how Task Manager handles process termination. Take a look at the Pywin32 project. – Jason Mar 14 '21 at 06:35
  • @Jason Thanks, I found the solution from the Pywin32 project. – SuspiciousKitchen-7 Mar 15 '21 at 10:29

2 Answers2

2

Thanks to Andrew D. bond's answer I found the solution. The code is working fine in windows.

import win32con
import win32api
import win32gui
import win32process
import psutil

def enumWindowsProc(hwnd, lParam):
    if (lParam is None) or ((lParam is not None) and win32process.GetWindowThreadProcessId(hwnd)[1] == lParam):
        text = win32gui.GetWindowText(hwnd)
        if text:
            win32api.SendMessage(hwnd, win32con.WM_CLOSE)

def stop_app(app_exe):
    for process in psutil.process_iter():
        if process.name() == app_exe:
            win32gui.EnumWindows(enumWindowsProc, process.pid)

stop_app("chrome.exe")
0

Did you try using child_pid.send_signal(signal.SIGTERM)?

send_signal is a method from Process class

signal module documentation: https://docs.python.org/3/library/signal.html