Search code examples
c#.netprocesswaithandle

Logic to kill a process within a time limit


I want to ensure that my logic is correct here. I want to run a process for timeout seconds, if it runs for longer it should be immediately killed.

The completed flag should reliably indicate whether the process completed as intended, e.g was not killed, and did not crash or throw an exception.

Also, I am not positive if the check to process.HasExited is correct. If process.WaitForExit() returns false and Kill() succeeds, then will process.HasExited always be true? That would be my assumption but I wanted to confirm. Also, what if anything can be done if Kill() fails, besides just logging?

        using (process = new Process())
        {
            process.EnableRaisingEvents = true;
            process.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived); 
            process.Exited += new EventHandler(OnExited);

            process.StartInfo = startInfo;
            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            if (!process.WaitForExit(timeout))
            {
                try
                {
                    process.Kill(); 
                }
                catch (Exception e)
                {
                    LogError(e, MethodBase.GetCurrentMethod());
                }
                finally
                {
                    this.completed = false;
                }
            }
            else
            {
                if (process.HasExited)
                {
                    this.code = process.ExitCode; 
                    this.completed = true;
                }
                else
                {
                    this.completed = false; 
                }
            }
        }

Solution

  • Yes, the HasExited will always be true in your case.

    According to MSDN,

    "A value of true for HasExited indicates that the associated process has terminated, either normally or abnormally.[...]A process can terminate independently of your code. If you started the process using this component, the system updates the value of HasExited automatically, even if the associated process exits independently."

    However, if your process crashes and terminates before your timeout, then your code will set it as completed anyway. Maybe you should check the exit code, but it can have different meanings for each process:

    if (process.ExitCode != 0)
    {
        this.completed = false;
    }
    

    For crashes, there are some approaches here and here, but generally you can't detect crashes for all processes.