Hi Eryk, I’m not sure if there has been any changes to the implementation of os.kill
in the last year, but I wanted to add to the discussion something I noticed when working with FastAPI and uvicorn.
Since Process.terminate()
is using TerminateProcess()
, using it for hot-reloading in uvicorn caused on_shutdown
events to be skipped, so it was changed to os.kill(self.process.pid, signal.CTRL_C_EVENT)
which correctly handles termination, but also kills any process that has been opened when using the multiprocessing
module or Popen
without the CREATE_NEW_PROCESS_GROUP
flag. This kills an Python console app when using uvicorn with reload in a subprocess.
A discussion was opened about a half year ago at the uvicorn repo, but hasn’t gained much traction, I guess because there is really no solution that covers all cases, short of CPython doing something about it or going back to Popen
.
Even if technically they are using os.kill
wrong according to the docs because they’re not using the proper flag, I think it’s somewhat frustrating that the higher-level multiprocessing
module does not offer a way to gracefully terminating a process in Windows, having to resort to os.kill
which is incompatible with multiprocessing
due to the impossibility of using creationflags
.
Also the os.kill
documentation is confusing as it suggests that you’re killing as specific process when in reality you’re calling GenerateConsoleCtrlEvent
on the whole group. Moreover, it does not refer to the need of using subprocess.CREATE_NEW_PROCESS_GROUP
, which might lead to incorrect use (such is the case with uvicorn)
I think the culprit is Win32 at the end of the day for not providing a API function to gracefully terminate a single process, but perhaps CPython could work around it by providing multiprocessing.Process
with a new parameter like create_new_group
, or maybe just take creationflags
like Popen
does.