Interesting open3 redirection problem

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
Consider this little complete perl program, intended to imitate a
gcc -v -E -x c - </dev/null >/dev/null

#!/usr/bin/env perl

use warnings;
use strict;
use File::Spec;
use IPC::Open3;

# WORKS: shell$ gcc -v -E -x c - </dev/null >/dev/null
# WORKS: my @cmd = ('gcc', '-v', '-E', '-x', 'c', '/dev/null');

# This one never gets out of the while loop.
my @cmd = ('gcc', '-v', '-E', '-x', 'c', '-');

if (open (my $NULLOUT, ">", File::Spec->devnull)) {
  if (open (my $NULLIN, "<", File::Spec->devnull)) {
    my $pid = open3 ($NULLIN, $NULLOUT, \*CMD, @cmd);
    while (<CMD>) {
    print "left while(<CMD>)\n";
    waitpid ($pid, 0);
    close CMD;
    close $NULLIN;
  close $NULLOUT;

I wonder why it never gets out of the "while" loop, but apparently
hangs somewhere waiting to read input that never arrives (after
printing gcc's stderr correctly). ps(1) says its wait channel it
$ ps -o wchan,args|grep perl
piperd perl ./ (perl5.8.8)

I'm stumped. Does any perl guru know what's going on and how to
correct the situation?

Regards, Jens

Re: Interesting open3 redirection problem wrote:
Quoted text here. Click to load it

First you open $NULLOUT to be a handle hooked up to write to null.
Then you close it, and reopen it to be a handle hooked up to write to
gcc (which means gcc is hooked up to read, as its stdin, what you write
to $NULLOUT).  Since you neither write to nor close $NULLOUT, gcc blocks
waiting for you to do one of those.

Quoted text here. Click to load it

If you want gcc to read directly from the handle, (rather than read what
Perl writes *to* that handle) then the docs to open3 say you specify the
first argument to open3 to start with "<&" (which means you probably
can't use a lexical filehandle, at least not easily)

Of course, to do that, you should open the handle $NULLIN to be read
from, not written to, or else gcc will complain that its stdin is not
open for reading.

But if you want @cmd to inherit a close file stdin, why not just specify
a first argument of undef to open3?


Site Timeline