Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

How to get Process output during execution

Moderators: larsivi kris

Posted: 03/16/08 06:14:11

I'm running a child process and I want to display it's output in a DFL text box while it's running. I don't seem to be getting any data from stream until after the program finishes, however. The code (very unkempt for now) is below. Am I doing it right (more or less?) Can this be done? (I might be running an outdated version of Tango- might I need to upgrade?)

TIA for any help

~John

		Process updPro = new Process(cmd, null);
		updPro.execute();
		
		do {
			foreach (line; new LineIterator!(char)(updPro.stdout))
				updLines ~= line;
			foreach (line; new LineIterator!(char)(updPro.stderr))
				updLines ~= line;
			TextBox.lines = updLines;
			Thread.sleep(0.1);
		} while (updPro.isRunning());
		
		auto result = updPro.wait();

		foreach (line; new LineIterator!(char)(updPro.stdout))
			updLines ~= line;
		foreach (line; new LineIterator!(char)(updPro.stderr))
			updLines ~= line;
		TextBox.lines = updLines;
Author Message

Posted: 03/16/08 18:15:05

perhaps the child is not flushing the output until it ends?

Posted: 03/16/08 18:15:57

Might just be that the child process is buffering the output. Tango's console IO switches to buffered mode when it detects that it's being redirected.

And you should probably .dup the lines, so they won't get overwritten when the buffer is refilled.

Posted: 03/17/08 17:03:21

the first foreach statement will not exit until the pipe is closed, which usually happens only on process termination. I.e. the updLines ~= line; line is running as the child is outputting each line, but that loop never exits until the child exits.

The way you have written the code, you might also get into a situation where the stderr pipe buffer is filled up completely and the child process is blocked trying to write to stderr while the parent is blocked trying to read from the child's stdout.

I have a similar program which sends updated stdout/stderr output through a net connection to a server, and it is not a simple task. On Linux, it's much easier, but basically, I use a tango.io.selector.Selector. On Windows, because there is no "wait for output" function for an anonymous pipe, I have a thread per child process polling each pipe every second to see if new data is present. This part might not apply to you, but in order to process the network traffic and the pipe traffic in one thread, I open a socket to myself so I can add that socket to the selector.

torhu's comments about .dup also are very important.

-Steve

Posted: 03/19/08 00:12:51 -- Modified: 03/19/08 00:13:38 by
teqdruid

Thanks for the help- turned out to be a combination of the two. The called program is an app I coded in C... I thought the std c lib always flushed on newlines, but looks like it wasn't flushing the buffer that often to the pipe, so I had to put a few fflush()s in it. I also didn't realize that the foreach line wouldn't exit until the program closed- didn't realize that the line iterators read until EOF- I figured they'd go until they couldn't read without blocking. Anyway, it wasn't updating the textbox properly. I've also added the .dup- I probably should have realized that one- I used to be pretty familiar with the Mango/Tango buffer-slicing-heap-management-fo-shizzle strategy... I guess it's been a bit too long since I've done much serious D programming.

Thanks for your help everyone!

~John