19

How would I go about killing a process on Windows?

I am starting the process with

    self.p = Process(target=self.GameInitialize, args=(testProcess,))
    self.p.start()

I have tried

self.p.kill()
self.p.terminate()
os.kill(self.p.pid, -1)
os.killpg(self.p.pid, signal.SIGTERM)  # Send the signal to all the process groups

Errors

Process Object has no Attribute kill
Process Object has no Attribute terminate
Access Denied

I cannot use .join.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
marsh
  • 2,592
  • 5
  • 29
  • 53

4 Answers4

25

On windows, os.killpg will not work because it sends a signal to the process ID to terminate. This is now how you kill a process on Windows, instead you have to use the win32 API's TerminateProcess to kill a process.

So, you can kill a process by the following on windows:

import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)

If the above does not work, then try signal.CTRL_BREAK_EVENT instead.

Games Brainiac
  • 80,178
  • 33
  • 141
  • 199
  • There is no `os.killpg` in Windows, and the `os.kill` implementation is deeply conflated and confused. It tries `GenerateConsoleCtrlEvent` if the 'signal' is either `CTRL_C_EVENT` (0) or `CTRL_BREAK_EVENT` (1). Otherwise it opens handle to the process and calls `TerminateProcess(handle, signal)`. – Eryk Sun Jan 22 '20 at 18:43
  • The confused part is that `GenerateConsoleCtrlEvent` targets a console process *group*. For a group target, POSIX `kill` requires a negative ID value, so this is wrong from the outset. Also, Windows provides no way to query a console process group ID, so the only way this makes sense (and everything else is extremely buggy) is to use group 0 (all console client processes) or to create the process as a new group with the flag `CREATE_NEW_PROCESS_GROUP`, for which the PGID is the PID. With this flag, Ctrl+C is initially disabled in the process, so only `CTRL_BREAK_EVENT` is reliable. – Eryk Sun Jan 22 '20 at 18:44
  • If the process either has no console or isn't attached to the same console as the calling process, then `GenerateConsoleCtrlEvent` fails. In this case, `os.kill` continues on to try `TerminateProcess`, but in CPython this is buggy (inexcusably, but no one has patched it) because the previous exception hasn't been cleared, which leads to a `RuntimeError`. If you know a process doesn't share the same console as your process, do not even try sending `CTRL_BREAK_EVENT`. It's not worth the headache. Just use `os.kill(pid, status)`, where `status > 1`. – Eryk Sun Jan 22 '20 at 18:51
  • 2
    I'm using multithreading and a queue in my calling program and it sometimes receives the KeyboardInterrupt instead of the child process -- what the hell?? – xjcl Dec 07 '20 at 14:01
14

I had to do it using this method from this link:

subprocess.call(['taskkill', '/F', '/T', '/PID',  str(self._active_process.pid)])

This is because self._active_process.kill() was not adequate

TinyTheBrontosaurus
  • 4,010
  • 6
  • 21
  • 34
  • 1
    Fantastic, the subprocess does stop, my output on windows was: SUCCESS: The process with PID 9028 (child process of PID 25224) has been terminated. SUCCESS: The process with PID 25224 (child process of PID 10340) has been terminated. SUCCESS: The process with PID 10340 (child process of PID 18632) has been terminated. Thank you ! splendid work – Mohammed Baashar Jun 21 '20 at 03:32
3

You should provide a minimal, working example of the problem you are having. As show below, this minimal, working example correctly terminates the process (Tested on Python 2.7.5 64-bit), so the error you are seeing lies in code you haven't shown.

import multiprocessing as mp
import time

def work():
    while True:
        print('work process')
        time.sleep(.5)

if __name__ == '__main__':
    p = mp.Process(target=work)
    p.start()
    for i in range(3):
        print('main process')
        time.sleep(1)
    p.terminate()
    for i in range(3):
        print('main process')
        time.sleep(.5)

Output:

main process
work process
work process
main process
work process
work process
main process
work process
work process
main process
main process
main process
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • This is good indeed, but it seems, Python's multiprocessing.Process isnt very class friendly! Did you try this in a class? – Hossein May 04 '20 at 10:53
  • 1
    @Rika Yes, converting `work` to a class derived from `Process` and with the work in a `def run(self):` works the same way. `p = Worker()` then gives the same result. If you have a problem post a question with a [mcve]. – Mark Tolonen May 04 '20 at 21:57
  • Thanks, the issue is not the worker itself, is the other class that will use worker to run the subprocess. at the very least, worker would accept an instance of the class in question, and simply execute the method which needs to be run as a seaprate thread. ```class Worker(multiprocessing.Process): def __init__(self, obj, *args, **kwargs): super.__init__(*args, **kwargs) self.obj = obj def run(self): self.obj.cpu_intensive_method()``` but using this inside the main class will produce pickle error. ami I missing sth here? – Hossein May 05 '20 at 04:13
0
os.kill(self.p.pid, -9)

Works. I am unsure why -1 returns a access denied error but -9 does not.

marsh
  • 2,592
  • 5
  • 29
  • 53