As mentioned in one of the replies above, if the C program does not flush its stdout, its output will be buffered until the pipe connection has accumulated (I think) 8 KB or so of data (or else has finished its work), before the downstream process will get to see any data.
(When output goes directly to the terminal window, stdout does not get buffered -- the buffering applies when the output is going to a pipe or file. You could test this out by running your C program at the command line like this:
./myC.exe 10 10 1 abc > test.out
Then use another window to watch the size of the "test.out" file. If the C code is not flushing stdout at each printf statement, the file won't grow until the program has written 8K of data, or until it finishes, whichever comes first.)
And apart from the output buffering in the C program, if the strings being printed to stdout do not end in a line-feed, the perl script might still not print anything until it detects and EOF on the pipe. The default input record separator in perl is "\n" (with windows CRLF handled as needed in the default windows/perl setup) -- (update:) perl will keep reading into $_ on the first iteration of while (<>) until it gets a line-feed or EOF.
When people do those kinds of progress-report string outputs, they often terminate each print with "\r", so that each iteration overwrites the previous string. If your C program is doing that, have your perl script use "\r" as the input record separator (the perl-internal global variable "$/") -- update: in other words, do this: $/ = "\r";
And sometimes, the C code has been written so that the status output has no termination at all -- each iteration simply appends onto one line. If your C program is set up that way and you want to keep that "feature", you'll want to modify the C code to at least use some distinctive character (or string) at the end of each report iteration, so the perl script can use that character (or string) as the input record separator. | [reply] [d/l] [select] |
Thank you all for your valuable inputs. I will ask the person who wrote the C program tomorrow to verify that his C program flushes its outputs after each print statement. I will report back the result on this forum tomorrow.
Thanks again.
| [reply] |
Not sure if this will help or not, but I had a similar problem a few years ago. On that occasion the progress message included a reference to a filename supplied via the command line. I discovered that by supplying a filename with a whole bunch of trailing spaces, it didn't affect the programs ability to open the file, but when it displayed the message it incorporated the trailing spaces. By adding enough spaces, it cause the pipe buffer to fill and so be output.
It doesn't look from your example that any of the parameters are paths, but if any of them are displayed as part of the progress message, you might try something like:
$data1 = sprintf "./myC.exe 10 10 1 \"abc%s\"", ' ' x 4096;
or even, if the executable name is part of the message:
$data1 = sprintf "%smyC.exe 10 10 1 abc", './' x 2048;
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
Thank you for your response. I can modify the C program to output the trailing spaces. Is there a way I can find out how big my system's buffer is so I can output the necessary trailing spaces?
| [reply] |
| [reply] [d/l] [select] |
Another option may be to setup a pseudo(fake) tty with IO::Pty, but I don't know if it works on MSWindows. Check how the following script runs your C.exe.
#!/usr/bin/perl -w
# Description: Fool a process into
# thinking that STDOUT is a terminal, when in fact
# it may be a file or a pipe. This can be useful
# with programs like ps and w on linux... which
# will trunc their output to the width of the
# terminal, and, if they cannot detect the terminal
# width, use a default 80 columns. Wouldn't it be
# nice to say "ps -aux | grep etcshadow", and get
# output that looks like when you just say "ps
# -aux"? Well, that's the idea.
#try ./pseudotty "xterm -e top"
#or ./pseudotty top
use warnings;
use strict;
use IO::Pty;
die "usage: ptyexec command [args]\n" unless @ARGV;
my $pty = IO::Pty->new;
my $slave = $pty->slave;
open TTY,"/dev/tty" or die "not connected to a terminal\n";
$pty->clone_winsize_from(\*TTY);
close TTY;
my $pid = fork(); die "bad fork: $!\n" unless defined $pid;
if (!$pid) {
# $slave->close();
open STDOUT,">&=".$pty->fileno() or die $!;
exec @ARGV;
}else{
$pty->close();
while (defined (my $line = <$slave>)) {
print $line;
}
}
#cleanup pty for next run
$pty->close();
| [reply] [d/l] |
It's working. You guys are great. After we put in the fflush(stdout) in the C program, everything works like a charm, Thanks again.
| [reply] |