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

hello,

I have multiple scripts running at the same time. Each scripts is running in its own windows command prompt instance.

I would like to have a master script that opens all the other scripts, and then collects the info from the other scripts.

I have been looking into using a piped open. The idea is to open each script from the master script with a statement like open JOB1, 'perl job1.pl|'. It kinda works except that I am having issues reading the data. I am trying to use IO::Select to know when there is data available to be read. I would be grateful if someone could look at my code and let me know if I am doing something wrong or if I am going about this the right way.

Thanks!

use IO::Select; my $read_set = new IO::Select(); #create handle set for reading open JOB1, 'perl test1.pl|' or die "cannot pipe to perl: $!"; open JOB2, 'perl test3.pl|' or die "cannot pipe to perl: $!"; my $read_set->add(JOB1); my $read_set->add(JOB2); while (1) { my $rh_set = IO::Select->select($read_set, undef, undef, 0); foreach my $rh (@$rh_set) { my $output = <$rh>; print $output2; print "in foreach $rh\n"; } } close JOB1; close JOB2;

Replies are listed 'Best First'.
Re: communication between programs
by Corion (Patriarch) on Sep 12, 2011 at 13:48 UTC

    IO::Select does not work with process pipes on Windows, mostly because select does not work with process pipe filehandles on Windows, and also because they can't be conveniently set into nonblocking read mode. If you really need to do this without threads, you have to transport the output of every process through TCP sockets, because they are selectable on Windows - see for example AnyEvent::Util::portable_pipe.

      hi, Thanks for the response. I guess this explains why I am getting the error message,
      "Can't call method "add" on an undefined value
      I will try with tcp pipes. thanks!!!
Re: communication between programs
by BrowserUk (Patriarch) on Sep 12, 2011 at 16:09 UTC

    When you've looked at all the complicated select-based work-arounds, try it the simple way :)

    #! perl -sw use strict; use threads; use Thread::Queue; $|++; our $THREADS //= 4; my $Q = new Thread::Queue; async { open my $pipe, '-|', q[ perl -E"$|++; sleep(1), say $$, ':', $_ for 1 .. 3" ] or die $!; $Q->enqueue( $_ ) while defined( $_ = <$pipe> ); $Q->enqueue( undef ); }->detach for 1 .. $THREADS; for ( 1 .. $THREADS ) { print while defined( $_ = $Q->dequeue ); } __END__ c:\test>925473.pl 4648:1 4764:1 704:1 1924:1 4648:2 4764:2 704:2 1924:2 4648:3 4764:3 704:3 1924:3

    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.
Re: communication between programs
by zentara (Cardinal) on Sep 12, 2011 at 14:31 UTC
Re: communication between programs
by moritz (Cardinal) on Sep 12, 2011 at 13:48 UTC
    . It kinda works except that I am having issues reading the data.

    What are these issues? What exactly happens? Do blue flames burst out of your computer?

    Looking over your code and the documentation seems to suggest that IO::Select->can_read returns a list, and you treat it as if it returned an array ref.

    You do Use strict and warnings, do you? Because you should.

Re: communication between programs
by ambrus (Abbot) on Sep 13, 2011 at 08:50 UTC

    I think your problem is that instead of

    my $rh_set = IO::Select->select($read_set, undef, undef, 0); foreach my $rh (@$rh_set) {
    you want
    my($rh_set) = IO::Select->select($read_set, undef, undef, 0); foreach my $rh (@$rh_set) {
    or
    my @rh_set = $read_set->can_read(); foreach my $rh (@rh_set) {

    The original code can't work, because it's not defined what the IO::Select->select method returns in scalar context (you're calling it like that), and in list context it returns a list of three references to arrays, the first being a reference to the array of readable handles.