1

I am starting a child process which should end within a defined timeout period along the following lines:

using (Process process = process.Start(startInfo))
{
    if (!process.WaitForExit(timeOutMilliSeconds))
    {
        if (!process.HasExited())
        {
            process.Kill();
        }
    }
}

The child process is a CPU-intense calculation engine (a SAT solver). My main program is written in C# and developed using Visual Studio 2013 and Windows 7 64-bit.

Most of the time, the above code works and a proper process timeout termination is accomplished. But in some 5% of the cases, process.Kill() has no visible effect. The child process remains active.

I have tried to start the child process with a lower priority. I also tried to suspend it before killing it. Calling TASKKILL /F as external tool also did not always help. I noticed, the problem does not occur for all SAT solvers. I have administrative rights but do not run the main program as Administrator.

What could I do to reliably terminate the child process of my application?

Edited:
Apart from exceeding their timeout budget, the child processes behave quite normal and can be killed manually using Process Explorer (without Administrator elevation). The question is how to make sure, that no process is left running after timeout.

Workaround:
I have implemented a timeout tool using VC++ 2013. Rather than calling the child process directly, I now call my tool which in turn calls the child process. The tool is using CreateProcess() and TerminateProcess() to start and stop the child process. It is probably possible to call CreateProcess() and TerminateProcess() from the C# program directly without spawning an additional process.
The workaround is not elegant, but it does solve my problem.

Axel Kemper
  • 10,544
  • 2
  • 31
  • 54
  • 1
    On Windows, not all IO is cancellable. Processes can get into an unkillable zombie state if they have uncancellable IO outstanding. That is very rare, though. – usr Jul 12 '14 at 20:18
  • From the documentation for `Kill`: "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. – Peter Ritchie Jul 12 '14 at 23:01
  • 1
    Also, try catching exceptions coming from Kill, it could be that an exception is being thrown and you're not seeing it because your app is terminating too. – Peter Ritchie Jul 12 '14 at 23:03
  • +1 for the epic title. =) – Chris Barlow Jul 15 '14 at 16:43

1 Answers1

0

I've made a child process management library where the parent process and the child process are monitored due a bidirectional WCF pipe. If either the child process terminates or the parent process terminates each other is notified. There is also a debugger helper available which automatically attaches the VS debugger to the started child process.

Maybe you can use it to control your child process.

Project site:

http://www.crawler-lib.net/child-processes

NuGet Packages:

https://www.nuget.org/packages/ChildProcesses https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/

Thomas Maierhofer
  • 2,665
  • 18
  • 33
  • In my application, the child processes are external third-party .exe processes which I cannot change. I just can use ordinary Windows mechanisms to watch the process state and issue kill commands. I might not fully understand your approach, but it does not look applicable to my case. – Axel Kemper Apr 09 '15 at 07:15
  • Oh, I thought the child process was also be written in C# by you. In deed my approach is not sufficient for third party processes. Have you tried to terminate your process without killing it. Killing a process can leave certain resource blocked and isn't possible all the time. – Thomas Maierhofer Apr 09 '15 at 19:17
  • Console applications are terminated by sending Ctrl-C and windows applications are terminated by sending a WM_CLOSE message. http://stackoverflow.com/questions/283128/how-do-i-send-ctrlc-to-a-process-in-c http://stackoverflow.com/questions/5402158/using-sendmessage-to-send-wm-close-to-another-process I would only kill a process if this doesn't work and the process really "hangs" – Thomas Maierhofer Apr 09 '15 at 19:21
  • Never mind! Thank you for your suggestions in any case. – Axel Kemper Apr 09 '15 at 19:22
  • I definitely had to kill the external processes as they simply exhausted their time budget and longer patience was not wortwhile. – Axel Kemper Apr 09 '15 at 19:24
  • I assume it is a console process. You can try Ctrl-C if you start the process from a CMD window. Normally it terminates your process immediately in a save way. In your application you can send Ctrl-C and poll the state for a second and kill the process if terminating by Ctrl-C wasn't successful. – Thomas Maierhofer Apr 09 '15 at 19:28
  • Yes. I am able to shut it down manually. But I am looking for an automated reliable way, as this time overrun happens in hundreds of batch jobs. – Axel Kemper Apr 10 '15 at 06:52