Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

<> operation with pipes

by seefurst (Initiate)
on May 08, 2012 at 15:45 UTC ( #969488=perlquestion: print w/replies, xml ) Need Help??
seefurst has asked for the wisdom of the Perl Monks concerning the following question:

So consider the following: It's not really secure, so don't use it. It's not Taint safe, it's just for discussion (let me know if this is the wrong section, apologies in advance).
use strict; use Parallel::ForkManager; use IO::Handle; my ($something, $somemaxnum) = @ARGV; pipe(DAREADER, DAWRITER); DAREADER->autoflush(1); DAWRITER->autoflush(1); sub onFinish { while (<DAREADER>) { ## read data from children print; } } my $fkmngr = new Parallel::ForkManager($somemaxnum); $fkmngr->run_on_finish(\&onFinish); for (1..$something) { $fkmngr->start and next; # child close DAREADER; print DAWRITER "some text"; close DAWRITER; } close DAWRITER; $fkmngr->wait_all_children; close DAREADER; __END__
Ok so this script deadlocks. Can anyone guess why?

What I find is this. With a short amount of text, it's fine.. but when the text gets larger or the forks end at various times the run_on_finsh subroutine doesn't leave the while loop. The while loop actually reads data from multiple forks, not just the one that finished (run_on_finish tells you the pid that just finished. On a few occations this number did not change yet data indicated that it was reading writes from a different fork which means that the funciton was executed once, after one fork ended).

However, the forks are still <defunct> (on solaris... ymmv), but the parent process is waiting for a read. Which means that <> is broken, I think, with pipes, because even though each fork has sent a close() to DAREADER, the parent process never receives EOF, and thus the subroutine never exits, wait() is never called.. etc... I mean yes, each file handle is copied however wouldn't close() send EOF down the pipe? Is this really broken or am I missing something?

The way I've worked around it is do ye olde 'dot-alone-on-a-line' trick and have each fork send a final "\n." which calls a last in the onFinish subroutine:

sub onFinish { while (<DAREADER>) { last if /^\.$/; print; } }
This will exit the subroutine, allow wait() to be callled, new forks to start and Parallel::ForkManager to do its thing (a great great module IMO!), however I can only guess why I need to do this DGRAM style and EOF just isn't failing the <> test.

Replies are listed 'Best First'.
Re: <> operation with pipes
by zwon (Abbot) on May 08, 2012 at 16:21 UTC

    You should add an exit statement in the end of the loop.

Re: <> operation with pipes
by tobyink (Abbot) on May 08, 2012 at 16:05 UTC

    I may well be completely on the wrong track, but $|?

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://969488]
Approved by Old_Gray_Bear
Front-paged by Old_Gray_Bear
and the questions are moot...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2018-05-23 23:34 GMT
Find Nodes?
    Voting Booth?