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

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

Comment on <> operation with pipes
Select or Download Code
Replies are listed 'Best First'.
Re: <> operation with pipes
by zwon (Monsignor) 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?
Username:
Password:

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
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (13)
As of 2015-07-30 19:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (273 votes), past polls