mangetsu has asked for the wisdom of the Perl Monks concerning the following question:

I have trouble using IPC::Open2 on Windows. I found some exmples online and wrote the code below. Based on what I've seen, it should work.
#!perl use strict; use warnings; use IPC::Open2; my $pid = open2(\*OUT, \*IN, '| findstr hello'); my $sometext = <<END; Hello, World! END print IN $sometext; close IN; my @found = <OUT>; print join " ", @found;
this codes just hangs when reading from OUT. I've tried using open2 before (with different programs) and never seems to get it to work. Am I doing something wrong?

Replies are listed 'Best First'.
Re: open2 on windows
by almut (Canon) on Dec 11, 2008 at 11:29 UTC
    my $pid = open2(\*OUT, \*IN, '| findstr hello'); ^

    You don't want the pipe in there...

     

    Update: Next thing to consider would be to add some form of error handling.  For example, this

    my $pid; eval { $pid = open2(\*OUT, \*IN, "NotThere ..." ); }; if ($@ and $@ =~ /^open2:/) { die "$@: $!\n"; }

    would produce

    > perl 729630.pl open2: exec of NotThere ... failed at 729630.pl line 8 : No such file or directory
      Thanks for your reply. I have tried what you have suggested, but I still have the same problem -- the script still hangs when reading from OUT. Here is what it looks like now:
      #!perl use strict; use warnings; use IPC::Open2; eval { my $pid = open2(\*OUT, \*IN, 'findstr hello'); }; if ($@ and $@ =~ /^open2:/) { die "$@:$!\n"; } my $sometext = <<END; Hello, World! END print IN $sometext; close IN; my @found = <OUT>; print join " ", @found;
      I have tried running this script on Cygwin (with grep instead of findstr), and it appear to work. So it seems the problem is with (how I use) findstr, or with open2 on Windows. Has anyone gotten open2 to work on Winows? Thanks.

        I've just played with this myself... and I think I can replicate your problem.  As I don't have findstr, I'm not entirely sure what it's doing, but I suppose it's some kind of 'grep', which reads lines from stdin, and writes lines to stdout if they match a given keyword.  So, I've used a little Perl program instead, which does the same.

        The issue under Windows seems to be that the "close IN" in your script does not generate an end-of-file on stdin of the process spawned. So, the program keeps reading/writing... In other words - as it doesn't terminate yet - it doesn't close stdout either, which in turn means that your "@found = <OUT>" is waiting for more lines to come (i.e. it 'hangs').

        The following test script demonstrates the issue:

        #!/usr/bin/perl use strict; use warnings; use IPC::Open2; my $pid; eval { $pid = open2(\*OUT, \*IN, qw(perl -ne), '$|=1; print if /hello/i') +; }; if ($@ and $@ =~ /^open2:/) { die "$@:$!\n"; } my $sometext = <<END; Hello, World! END print IN $sometext; close IN; # read/print line by line, so we see the output while (<OUT>) { print ":: $_"; }

        On Windows (tested with Perl 5.8.8 on XP), this prints ":: Hello, World!" and then hangs.  On Unix/Linux, it terminates after printing the line, as expected  (you can make it hang, too (like on Windows), by commenting out the line "close IN;").

        Anyhow, I'm no Windows gal, so I'm afraid I can't help you any further...

        BTW, an unrelated thing: in my original snippet, I had deliberately put the my $pid outside of the eval, because in case you'd need it later on, it would already have gone out of scope... — yes, you're not using it here, but just in case.

        ___

        (PS: <PerlMonks-meta> I normally don't frontpage nodes where I'm the first/only one who has replied (feels like XP-whoring to me)... but in this case I did, in the hope that it'll get some more exposure, and that someone windows-savvy will know more... </PerlMonks-meta>)