Can’t kill child process on Windows
The following will never exit
What’s going on here? also what is the correct thing to do here? The only way to make this process actually close is to kill the parent process. I suspect it’s waiting for stdio to flush or something like that?
It does die if it is given an ‘ignore’ stdio configuration, but I need the streams.
4 Answers 4
You are spawning child process cmd.exe by using babel.cmd . This process then starts another grandchild process node and runs babel script. When you do ps.kill() it only kills the cmd.exe but not the child processes created by it.
Although cmd.exe is closed, the stdio stream of the parent process is still shared with the other processes in the tree. So the parent process is waiting for the stream to be closed. Using stdio: ‘ignore’ will only stop sharing the stdio stream with other processes in the tree but those grandchild processes will still continue running.
Update:
After discussing with OP, I tested with all three stdio options: pipe (default), inherit , ignore in iojs 3.3.0, Windows 7 (32bit). None of them kills the grandchild process.
With inherit and ignore , both parent process and child process(cmd.exe) are killed but the grand child process still floats around and doesn’t belong to any process tree.
With pipe , only the child process is terminated but both parent and grand child process continue running. The reason that parent process is not exiting is most likely because the stdio of parent node.exe is still shared with the other processes as mentioned in original answer.
child.unref() doesn’t have any effect on killing grand child process. It only removes the child process from parent’s event loop so that the parent process can exit normally.
I could think of couple of solutions:
Invoke the babel.js directly without that cmd script:
Use windows taskkill command with \T flag to kill the process and all the child processes started by it:
Expand Process.Kill to Optionally Kill a Process Tree #24617
Comments
Copy link Quote reply
bgribaudo commented Jan 9, 2018
Issue
.Net Standard does not provide a means to kill a process tree (that is, a given process and all of its child/descendant processes).
In the Windows world, this can be done by assembling the list of descendant processes to terminate using WMI’s Win32_Process management object, performance counters or P/Invoke, then killing each one, then killing the parent/root process. However, since .Net Standard doesn’t provide a way to enumerate child/descendant processes, it’s impossible for a user to directly implement this approach in a cross-platform way using only .Net Standard.
If the ability to enumerate child processes were added (as #24423 proposes), there’d still be complexities involved with using the child process list to kill a process tree as care is needed to ensure that unrelated processes aren’t inadvertently terminated because of process ID reuse. This proposal saves the developer from needing to worry about such complexities and instead provides a simple, one-line way to terminate a process tree.
Rationale
Sometimes, it’s necessary to end a process tree. 🙂
For example, Microsoft.DotNet.Tools.Test.Utilities.ProcessExtension relies on different code paths to handle killing a process tree on Windows and Linux. Both code paths involve invoking one or more command-line processes. If this proposal were implemented, presumably this logic could be replaced with a single-line kill all method call followed possibly by a call to WaithForExit(int milliseconds) . No multiple code paths. No need to invoke command-line processes.
Another example: A project I’m currently working on uses integration tests that use Process to call dotnet run to start a server process. When the test has completed, it’s possible to use Process’s Kill() to end the parent dotnet process. However, this leaves child processes still running—which causes problems.
Proposal
Extend Process as follows:
Original (ignore—left for reference purposes):
Revision (ignore—left for reference purposes):
Approved Version:
With this change, Kill will behave exactly as it does at current if it is called with no arguments or with false as its argument. However, when called with true as its argument, in a platform-appropriate way all descendant processes will be killed, followed by the process represented by the current Process instance.
[edited by @danmosemsft to add c# formatting only]Process. Kill Method
Definition
Forces termination of the underlying process.
Overloads
Immediately stops the associated process.
Immediately stops the associated process, and optionally its child/descendent processes.
Remarks
The Kill method forces a termination of the process, while CloseMainWindow only requests a termination. When a process with a graphical interface is executing, its message loop is in a wait state. The message loop executes every time a Windows message is sent to the process by the operating system. Calling CloseMainWindow sends a request to close the main window, which, in a well-formed application, closes child windows and revokes all running message loops for the application. The request to exit the process by calling CloseMainWindow does not force the application to quit. The application can ask for user verification before quitting, or it can refuse to quit. To force the application to quit, use the Kill method.
The behavior of CloseMainWindow is identical to that of a user closing an application’s main window using the system menu. Therefore, the request to exit the process by closing the main window does not force the application to quit immediately.
The Kill method executes asynchronously. After calling the Kill method, call the WaitForExit method to wait for the process to exit, or check the HasExited property to determine if the process has exited.
The WaitForExit method and the HasExited property do not reflect the status of descendant processes. When Kill(entireProcessTree: true) is used, WaitForExit and HasExited will indicate that exiting has completed after the given process exits, even if all descendants have not yet exited.
Data edited by the process or resources allocated to the process can be lost if you call Kill . Kill causes an abnormal process termination and should be used only when necessary. CloseMainWindow enables an orderly termination of the process and closes all windows, so it is preferable for applications with an interface. If CloseMainWindow fails, you can use Kill to terminate the process. Kill is the only way to terminate processes that do not have graphical interfaces.
You can call Kill and CloseMainWindow only for processes that are running on the local computer. You cannot cause processes on remote computers to exit. You can only view information for processes running on remote computers.