Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

What is the preferred cross-platform IPC module?

by Theory (Beadle)
on May 13, 2012 at 06:51 UTC ( #970244=perlquestion: print w/ replies, xml ) Need Help??
Theory has asked for the wisdom of the Perl Monks concerning the following question:

I want to create a simple IO object that represents a pipe opened to another program to that I can periodically write to another program's STDIN as my app runs. I want it to be bullet-proof (in that it catches all errors) and cross-platform. The best options I can find are:

open

sub io_read { local $SIG{__WARN__} = sub { }; # Silence warning. open my $pipe, '|-', @_ or die "Cannot exec $_[0]: $!\n"; return $pipe; }

Advantages:

  • Cross-platform
  • Simple

Disadvantages

  • No $SIG{PIPE} to catch errors from the piped program
  • Are other errors caught?

IO::Pipe

sub io_read { IO::Pipe->reader(@_); }

Advantages:

  • Simple
  • Returns an IO::Handle object for OO interface
  • Supported by the Perl core.

Disadvantages

  • Still No $SIG{PIPE} to catch errors from the piped program
  • Not supported on Win32 (or, at least, its tests are skipped)

IPC::Run

There is no interface for writing to a file handle in IPC::Run, only appending to a scalar. This seems…weird.

IPC::Run3

No file handle interface here, either. I could use a code reference, which would be called repeatedly to spool to the child, but looking at the source code, it appears that it actually writes to a temporary file, and then opens it and spools its contents to the pipe'd command's STDIN. Wha?

IPC::Cmd

Still no file handle interface.


What am I missing here? It seems as if this should be a solved problem, and I'm kind of stunned that it's not. IO::Pipe comes closest to what I want, but the lack of $SIG{PIPE} error handling and the lack of support for Windows is distressing. Where is the piping module that will JDWIM?

Comment on What is the preferred cross-platform IPC module?
Select or Download Code
Re: What is the preferred cross-platform IPC module?
by BrowserUk (Pope) on May 13, 2012 at 08:38 UTC
    IO::Pipe ... the lack of support for Windows

    This has worked fine for me since (from memory) 5.8.1 or .2; when I helped demerphq fix it:

    perl -MIO::Pipe -e"$p=IO::Pipe->new; $p->reader('dir /b'); print while + <$p>"

    I'm not sure why the tests are skipped on Win32, but then much of reasoning behind the entire Perl build process is a mystery to me.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    The start of some sanity?

      Good to know, thanks. Perhaps I should report it as a bug to p5p.

      But I could not see anywhere where it does something with $SIG{PIPE}. I assume that is something I would still have to do myself. I do not want to. I want errors form the child to simply be thrown as exceptions. Is $SIG{PIPE} the only error handler that needs to be installed? And there is no way to lexically scope it, either.

      What I'm thinking of now is some sort of OO interface, call it IPC::Simple, where you instantiate by passing it the command, it does all of the IPC error handling for you, turning stuff into exceptions (not unlike IPC::System::Simple does for system and backticks), and accessors for the STDIN, STDOUT, and STDERR file handles. I Just need STDIN for my current app, but I think a more generally useful Open3-based solution that properly scopes IPC error handling to throw exceptions would be very useful. IPC::Pipe is close-ish, but does not do the error handling stuff, I looks like. AMIRITE?

        But I could not see anywhere where it does something with $SIG{PIPE}.

        Windows doesn't do signals. Perl emulates a few for compatibility, but sigpipe isn't one of them.

        IMO, Windows and *nix/POSIX IPC are just too different to successfully wrap them over in a common interface. I've not found a single 'portable' module that works well on Windows.

        As such, I believe that it is better to move the platform dependency out of the IPC module to the level above, and call a platform specific subroutine to perform the IPC.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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.

        The start of some sanity?

      turns out that, for my needs, I need to be able to write to the target's STDIN and read from its STDOUT. I started implementing the module I have been imagining, but it looks like I really should read the IPC::Run docs more closely before I go any further with it. Although its docs say that Win32 support is experimental…

        Take a look at winopen2() in Win32::SocketPair.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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.

        The start of some sanity?

Re: What is the preferred cross-platform IPC module?
by choroba (Abbot) on May 13, 2012 at 09:16 UTC
    Crossposted at stackoverflow. It is considered polite to inform about crossposting so people do not waste time on a problem already solved at the other site.

      You're right, sorry about that. I was curious to see how the replies would vary between the two sites, but should have mentioned on PM, at least, that I was cross-posting.

Re: What is the preferred cross-platform IPC module?
by pklausner (Scribe) on May 14, 2012 at 12:44 UTC
    For similar purposes I am pondering to use 0MQ / ZeroMQ which is a stripped down, broker-less AMPQ. It also offers Perl bindings. Do monks with more experience with this module think this summary is correct?

    Advantages:
    • cross-platform
    • supposedly simple programming model
    • supposedly robust
    Disadvantages:
    • requires extra binary lib
    • API still in flux
    • still no file handle interface
Re: What is the preferred cross-platform IPC module?
by runrig (Abbot) on May 14, 2012 at 16:36 UTC
    There is no interface for writing to a file handle in IPC::Run, only appending to a scalar. This seems…weird.

    Not sure what you mean here. This works fine:

    use IPC::Run qw(start run); open(my $in, "<", "in.txt") or die "Err: $!"; open(my $out, ">", "out.txt") or die "Err: $!"; my @cat = '/bin/cat'; my $h = run \@cat, $in, $out; close $in; close $out;
      I want file handles I can interactively read (from the target process's STDOUT) and rite (to the target process's STDIN). @Ikegami pointed out on the SO post that is possible to do this with IPC::Run; I just haven't read the docs closely enough.
Re: What is the preferred cross-platform IPC module?
by Anonymous Monk on May 14, 2012 at 17:05 UTC

    I'm probably be tarred and feathered for suggesting this but one module that would seem to meet all your requirements is IO::Socket::INET.

    Sure, there may be a bit of performance overhead for using a full blown socket but sockets are robust, cross-platform, and capable of error detection.

Re: What is the preferred cross-platform IPC module?
by Theory (Beadle) on May 22, 2012 at 05:15 UTC

    After losing three days or so to investigating this, I gave up. Commenters on a blog post pointed out how I could resolve database-specific packaging issues, and that freed me to just stop worrying and to use the DBI instead.

    FWIW, I did write up a detailed SO answer to the original question. TL;DR: IPC::Run is probably the best choice, but IPC is such a mess that all the options frankly suck pretty hard. I am grateful I don't have to deal with it anymore.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://970244]
Approved by Old_Gray_Bear
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2014-10-25 23:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (149 votes), past polls