Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Alternative for Select for pipes in Windows?

by matematiko (Novice)
on Nov 05, 2010 at 17:24 UTC ( [id://869704]=perlquestion: print w/replies, xml ) Need Help??

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

Dear monks;

I am a winblowz user using ActiveState 5.10.

I need to create a perl script (probablly convert it to exe later) that will be spawn by another c++ exe. Two anonymous unidirectional pipes will be created by the parent, one to be the child (my script) STDIN and the other one to be the child STDOUT.

Additionally, my script will open a named pipe to communicate with another program already running but is not my child.

Of course the script must enter an infinite loop, listen constantly for parent and the other program commands and produce a result accordingly.

I have done this before when a script communicates to more than one socket using IO::Select. Example:

# I am just showing some pieces of the code of course $net=new IO::Socket::INET(Proto => 'tcp', PeerAddr => $someserver, Pee +rPort => $someport); . . . $sel=new IO::Select($stdin,$net,$net2); . . . while (1) { foreach my $x ($sel->can_read(0.05)) { if ($x==$net) { &dosomething1; $net->flush; } elsif ($x==$net2) { &dosomething2; $net2->flush; } else { sysread($x,$in,1) or exit; if ($in eq "\n") { &dosomething3 $buffer; $buffer=''; $net->flush; } elsif ($in ne "\r") { $buffer.=$in; } } } }

The problem I have is that after many attempts, my script did not work. Then yesterday I read somewhere that under windows, IO:Select works only with sockets not with pipes.

Is there a known alternative for this scenario? I will really hate to have to learn another programming language.

Resuming:

-An existing program spawns my program and creates two anonumous pipes for STDIN and STDOUT

-My program opens a named pipe with another already running program which is not my child.

-My program should run in infinite loop, listen to both programs and "do something".

A simple example will do the trick.

Thanks a lot in advance.

EDIT: Confirmed.... Win32::Socketpair fails to run in two different Windows distros (Strawberry 5.12 and ActivePerl 5.10) Since this suggestion is the more sound one I had found, I will continue to troubleshoot why Win32::Socketpair fails.... thanks for the help

Replies are listed 'Best First'.
Re: Alternative for Select for pipes in Windows?
by ikegami (Patriarch) on Nov 05, 2010 at 17:36 UTC

    One way:

    use threads qw( async ); use Thread::Queue qw( ); my $q = Threads::Queue->new(); async { while (<STDIN>) { $q->enqueue(...); } $q->enqueue(...); }; async { while (<$fr_child_pipe>) { $q->enqueue(...); } $q->enqueue(...); }; while (defined(my $item = $q->dequeue())) { ... }

    Thread::Queue


    Another solution would be to create socket pairs (which are selectable), and have threads that simply convert the pipes into sockets. That would allow you to use existing code.

    use threads qw( async ); use Win32::Socketpair qw( winsocketpair ); my ($fr_parent_sock, $fr_parent_sock_writer) = winsocketpair(); async { print($fr_parent_sock_writer $_) while <STDIN>; close($fr_parent_sock_writer); }; my ($fr_child_sock, $fr_child_sock_writer) = winsocketpair(); async { print($fr_child_sock_writer $_) while <$fr_child_pipe>; close($fr_child_sock_writer); }; ... select $fr_parent_sock and $fr_child_sock ...

    (You could avoid the second thread by tying the socket directly to the child's STDOUT.)

    Win32::Socketpair

    Update: Fleshed out the code for the second solution, and added a link to the module.

      Unfortunately, the installation of Win32-Socketpair fails in both: ActivePerl 5.10 and Strawberry 5.12. The make Test fails... I will try to force the installation in Starwberry anyways....In ActivePerl it proved to make perl hang when trying to run the script.

        Replace the winsocket pair sub with this:

        sub winsocketpair { my $proto = getprotobyname('tcp'); my $first = 1; for (1..5) { if ($first) { undef $first; } else { carp "winsocketpair failed: $!, retrying" } socket(my $listener, AF_INET, SOCK_STREAM, $proto) or return (); socket(my $server, AF_INET, SOCK_STREAM, $proto) or return (); socket(my $client, AF_INET, SOCK_STREAM, $proto) or return (); my $true = 1; ioctl($client, 0x8004667e, \$true ); my $addr = sockaddr_in(0, INADDR_LOOPBACK); bind($listener, $addr) or return (); listen($listener, 1) or return (); $addr = getsockname($listener); connect($client, $addr) or $! == 10035 or $! == EINPROGRESS or next; my $peer = accept($server, $listener) or next; my $false = 0; ioctl($client, 0x8004667e, \$false ); if ($peer eq getsockname($client)) { return ($server, $client); } } return (); }

        And ignore make test--the tests seem to be broken. They sometime pass and sometimes fail?


        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.
      One way ...

      How do you combine a select loop with a blocking dequeue?

        The dequeue loop replaces the select loop.
Re: Alternative for Select for pipes in Windows?
by BrowserUk (Patriarch) on Nov 05, 2010 at 17:50 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://869704]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-20 01:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found