C# .NET 3.5
I have a console application that is being called by another application on the computer. This console app runs continuously, and listens for data on stdin from the "parent" process.
However, when the parent is stopped or killed, the console app that it started continues. Under normal circumstances, it sits and idles waiting for input from stdin, using minimal resources. However, as soon as the parent goes away, this console app spikes the CPU and starves the core it's running on with near 100% utilization. This continues until I manually kill the process.
Ideally, the calling parent would clean up after itself, particularly since this is happening under normal (non exceptional) "stop" conditions. Unfortunately, this parent process is out of my hands.
My first thought was to grab the invoking parent from within the console app, and monitor its PID. If the parent process goes away, I the console app would terminate itself. Currently, I'm doing this by:
Process process = Process.GetCurrentProcess();
m_ParentPID = 0;
using (ManagementObject mgmtObj = new ManagementObject("win32_process.handle='" + process.Id.ToString() + "'"))
{
mgmtObj.Get();
m_ParentPID = Convert.ToInt32(mgmtObj["ParentProcessId"]);
}
string parentProcessName = Process.GetProcessById(m_ParentPID).ProcessName;
Log("Parent Process: " + parentProcessName + Environment.NewLine);
// Create a timer for monitoring self.
Timer timer = new Timer(new TimerCallback(sender =>
{
if (m_ParentPID != 0)
{
Process parent = System.Diagnostics.Process.GetProcessById(m_ParentPID);
if (parent == null)
{
Log("Parent process stopped/killed. Terminating self.");
System.Environment.Exit(0);
}
}
}));
// Kick on the timer
timer.Change(m_ExitWatcherFrequency, m_ExitWatcherFrequency);
This only partly works though - it stops the CPU spike, but if I look at my processes from Sysinternals wonderful process monitor, I can see DW20.exe running - the "Microsoft Application Error Reporting" program. And it just ... sits there, and the console app remains in memory.
What should I be doing here to correctly terminate the process to avoid this continuous CPU spike and unreleased memory? Eventually this needs to be running without intervention.
P.S. I am using a command line application here as a "long running program" instead of a Windows Service or web service because the parent program can only be configured to execute a command line app for which it passes data in via stdin. (for those who are curious, this is ejabberd, using external authentication).
EDIT:
The code that waits for input from stdin is:
// Read data from stdin
char[] charray = new char[maxbuflen];
read = Console.In.Read(charray, 0, 2);
I mention before that when the parent terminates, the console app goes crazy on the CPU. I attached a debugger to it from Visual Studio, and it is, in fact, still sitting on that line Console.In.Read. In theory then, when the self-monitoring timer triggers and sees the parent is gone, it attempts an System.Environment.Exit(0) when the other thread is on that Read() line.