in reply to Pipe, fork, exec and red-hot pokers.

While not a solution to your problem per se, I might suggest another approach to the redirection of command output using IPC::Open3 - The following snippet of code, duplicates the STDOUT and STDERR streams and calls open3 to execute the command, directing the output into the respective streams.

use Carp; use IO::Handle; use IPC::Open3; use strict; my $STDOUT = IO::Handle->new; my $STDERR = IO::Handle->new; open($STDOUT, ">&STDOUT") || croak( 'Cannot duplicate STDOUT to file handle - ', $! ); open($STDERR, ">&STDERR") || croak( 'Cannot duplicate STDERR to file handle - ', $! ); eval { open3( '<&STDIN', $STDOUT, $STDERR, "some_application" ) || die $!; waitpid(-1, 0); }; croak( 'Cannot execute command - ', $@ ) if $@; # The STDOUT and STDERR output of some_application # execution now resides in $STDOUT and $STDERR # respectively. eg. print $_ foreach <$STDOUT>

As always with Perl, TMTOWTDI.

 

Replies are listed 'Best First'.
Re: Re: Pipe, fork, exec and red-hot pokers.
by hagus (Monk) on Apr 09, 2002 at 00:56 UTC
    This doesn't work either - if my program prints something to stdout and runs *forever* (ie. a daemon) then I will get no output. If I put while (<$STDOUT>) just after the open3, then everything is silent.

    Unless my some_application itself sets $|=1 ... then I get output from it. If it's still buffered, I have to wait until the stdout buffer is full or the program terminates.

    What I want is to read the stdout of some_application, buffered or no, in real time. The key question is becoming: 'why isn't some_application flushing its buffer on newline?'

    Comments? Please? :)

    --
    Ash OS durbatulk, ash OS gimbatul,
    Ash OS thrakatulk, agh burzum-ishi krimpatul!
    Uzg-Microsoft-ishi amal fauthut burguuli.

      Interesting ... One thing which I would be looking to try at this point would be to incorporate autoflush on the created duplicate handles prior to the open3 invocation. eg.
      my $STDOUT = IO::Handle->new; my $STDERR = IO::Handle->new; open($STDOUT, ">&STDOUT") || croak( 'Cannot duplicate STDOUT to file handle - ', $! ); open($STDERR, ">&STDERR") || croak( 'Cannot duplicate STDERR to file handle - ', $! ); $STDOUT->autoflush; $STDERR->autoflush;

      If you still have no joy with this, you may have to incorporate a flush of the respective buffer prior to reading from it. eg. $STDOUT->flush. This may be necessary if some_application is actively buffering its output.

      I'd be very interested to hear how you go with this and see if this resolves your problems with your specific application.

       

        No dice ... :( Same result.

        Here's my current theory. some_application believes that it's not running on a terminal (correctly), so it stops line buffering for some reason. It *does* flush its buffers on termination and on reaching the 4096 buffer limit (or whatever the precise number is).

        So perhaps another avenue to persue is fooling some_application into thinking that $STDOUT is in fact a tty?

        --
        Ash OS durbatulk, ash OS gimbatul,
        Ash OS thrakatulk, agh burzum-ishi krimpatul!
        Uzg-Microsoft-ishi amal fauthut burguuli.