0

I have a pair of Windows console programs, parent written in C#, child written in C; the parent calls the child with a filename as argument, gets output, waits for exit, calls again with the next in a list of data files and so on. Going through the entire list of data files could take many hours, so in testing I usually want to kill the parent process with ^C, figuring if any child process is still running, if it doesn't die because of that, it should be killed a few seconds later by the timer it sets.

What actually happens is the parent process exits, I get the console back, but the child process is still there in the background, using no CPU, hung permanently until killed with task manager. Why is that happening, and how can it be prevented?

Parent process calling code:

            var worker = new Process()
            {
                StartInfo = new ProcessStartInfo("/ayane/ayane.exe", "-t=10 " + filename)
                {
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                }
            };
            worker.Start();
            var output = worker.StandardOutput.ReadToEnd();
            worker.WaitForExit();

Child code that sets a timer to kill the process if it hasn't finished in a few seconds:

static VOID CALLBACK timeout(PVOID a, BOOLEAN b) { ExitProcess(0); }

...

  HANDLE timer = 0;
  CreateTimerQueueTimer(&timer, 0, timeout, 0, (DWORD)(time_limit * 1000),
                        0, 0);

Update: I tried a test just now where I took out the RedirectStandardOutput and RedirectStandardError so presumably it's not a pipe situation any more, and the problem still happens exactly the same way, so it doesn't seem to be to do with redirection and broken pipes after all.

rwallace
  • 31,405
  • 40
  • 123
  • 242
  • 1
    The hang is presumably because the child is attempting to write to the now-dead standard output, although normally I'd expect that to result in an exception. Might be a bug in .NET or something about your child program - we'd need a [mcve] to tell. The timer won't work because it requires a GUI message loop, and the child is a console program. – Harry Johnston Feb 24 '17 at 05:16
  • 3
    In a C program I would recommend putting the child process into a job, so that it can be automatically killed when the parent dies. I'm not sure how easy it is to do that in C#. – Harry Johnston Feb 24 '17 at 05:17
  • @HarryJohnston You say the timer won't work in a console program, but I tried running the child program by itself just now to make sure, adding an infinite loop in the main function but telling it to time out in two seconds, and it timed out just fine. – rwallace Feb 24 '17 at 05:20
  • 1
    @HarryJohnston See [Kill child process when parent process is killed](http://stackoverflow.com/questions/3342941/). – Remy Lebeau Feb 24 '17 at 06:00
  • rwallace, sorry, I was confused. SetTimer() doesn't work in console programs. CreateTimerQueueTimer() should. My best guess at this point is that your client is hanging during process exit, probably inside the destructor of a global object. – Harry Johnston Feb 24 '17 at 23:52
  • @HarryJohnston I understand where you're coming from, but the client is written in C not C++, exits normally when called directly from the console, and for that matter exits normally when called from the parent program when I don't interrupt the parent with ^C. – rwallace Feb 25 '17 at 03:16
  • Well, there must be *something* wrong with the client. :-) But without a [mcve] all we can do is guess ... it has only just occurred to me to wonder why the client isn't being killed by the control-C, what happens if you start the client from the console and press control-C while it is running? – Harry Johnston Feb 25 '17 at 05:52
  • @HarryJohnston Client running by itself dies to ^C just fine. – rwallace Feb 25 '17 at 17:11
  • I don't *think* .NET suppresses ^C for child processes. You could try with a simple child that does nothing but call `Sleep(INFINITE);` and see what happens there. Have you tried connecting a debugger to your child while it is hung to see what is happening? – Harry Johnston Feb 25 '17 at 19:31

0 Answers0