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

I'm stuck trying to figure out why my usage of IPC::Open2 isn't working how I expect.

This works:

perl -e 'package MyPack; sub foo { use IPC::Open2; my ($in, $out); my $pid = open2($out, $in, q[program --unbuffered]); print $in q|some json|; my $result = <$out>; warn "got [$result]\n"; close($in); close($out); waitpid($pid, 0); } 1; package Main; MyPack->foo();'

It prints my expected result in square brackets after taking some time to calculate the result.

But if I have lib/MyPack.pm:

package MyPack; sub foo { use IPC::Open2; my ($in, $out); my $pid = open2($out, $in, q +[program --unbuffered]); print $in q|some json|; my $result = <$out>; + warn "got [$result]\n"; close($in); close($out); waitpid($pid, 0); } 1;

and do:

perl -Ilib -MMyPack -e 'MyPack->foo();'

It returns immediately with an empty result set (json empty square brackets inside my printed square brackets). foo() in both cases is copy/pasted. Why doesn't it work from inside a .pm?

Edit for more: Fully copy/pasting the entire contents of the perl 1 liner that works in to lib2/MyPack.pm, and then calling:

perl -Ilib2 -e 'use MyPack;'

also doesn't work. What can it be about having the code inside a .pm that could stop it working?

Edit for solution: my input json string had single quotes, which behaved differently on the command line and inside a .pl or .pm. Removing the quotes made them both behave the same.

Replies are listed 'Best First'.
Re: Why is IPC::Open2 behaving differently in a .pm?
by shmem (Chancellor) on Aug 14, 2015 at 16:26 UTC

    No way to tell without knowing what program is and does. I've coded program as follows

    #!/usr/bin/perl $_ = <STDIN>; chomp; print "foo => '$_'";

    and both the command line version and the module version worked as expected after changing

    - print $in q|some json|; + print $in "some json\n";

    Maybe you have to set local $| = 1; inside your MyPack.pm (see perlvars)? Looks like a buffering issue - despite --unbuffered ;-)

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      With program as you specify it, both work. With my own program (baton-metaquery from https://github.com/wtsi-npg/baton), even with local $| set, it doesn't.

      However the question is why the 1-liner with the in-line MyPack package works, but copy/pasted MyPack code in to a .pm does not work. How can that be possible?

        Because that isn't the actual source of the difference. You have just convinced yourself that it is. And then you posted code but removed the parts that you don't think are the cause of the difference and people have shown that this incomplete code (when made to actually work) doesn't demonstrate that difference.

        The problem is in the parts that you didn't post.

        - tye