OK, woah. Slow down there. You're doing threads and fork in the same code. That's a really horrible idea. They're somewhat implementation dependent - you can be pretty sure they'll work, but both at the same time is asking for a world of pain. (Concurrency issues, race conditions, etc.).
In this particular case - you need to understand that what fork() does is take a complete copy of your process - in exactly the same state - and has a single difference - the return code of fork(). That means that the threads etc. will be cloned by the fork() too. Parallel::ForkManager is hiding some of that from you, by limiting the parallelism scope, but that's what's going on behind the scenes.
I'd urge you to step back and make a rewrite - what you appear to be doing would be MUCH better suited to using some worker threads and a Thread::Queue:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
use Thread::Queue;
#parallelism limit
my $num_threads = 5;
#input and output queues
my $work_q = Thread::Queue -> new();
my $result_q = Thread::Queue -> new;
#jobs as before
my @jobs = ('a', 'b', 'c', 'd', 'e', 'f', 'g');
#worker - reads from queue one item at a time.
#exits if the queue is 'undef' which happens if it has been `end`ed.
sub worker {
while ( my $item = $work_q -> dequeue ) {
print threads -> self -> tid.": processing work item $item\n";
#pretend we did some work, queue the result.
$result_q -> enqueue ( threads -> self -> tid . ": finished $item" );
}
}
#spawn threads
threads -> create (\&worker) for 1..$num_threads;
#queue jobs
$work_q -> enqueue ( @jobs );
#close queue, so threads will exit when they hit the end of the queue.
#dequeue will return 'undef' rather than blocking.
$work_q -> end;
#join all the threads.
$_->join for threads -> list;
#all threads are finished, so we close the result queue.
#again - so dequeue is undef when empty, rather than just blocking.
$result_q -> end;
while ( my $result = $result_q -> dequeue ) {
print "Got result of $result\n";
}
print "All done\n";
Since you indicate that you're looking to run the 'result_q' in parallel too, then you can do the same thing with the 'result handler' as another thread, with much the same result.
This gets slightly ticklish, in that you do need to know your 'exit' condition based on open/closed queues. But something like this:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
use Thread::Queue;
#parallelism limit
my $num_threads = 5;
#input and output queues
my $work_q = Thread::Queue->new;
my $result_q = Thread::Queue->new;
#jobs as before
my @jobs = ( 'a', 'b', 'c', 'd', 'e', 'f', 'g' );
#worker - reads from queue one item at a time.
#exits if the queue is 'undef' which happens if it has been `end`ed.
sub worker {
while ( my $item = $work_q->dequeue ) {
print threads->self->tid . ": processing work item $item\n";
#pretend we did some work, queue the result.
$result_q->enqueue( threads->self->tid . ": finished $item" );
}
}
#a thread to process the results in parallel
sub collator {
while ( my $result = $result_q->dequeue ) {
print "Got result of $result\n";
}
}
#spawn threads
my @workers = map { threads->create( \&worker ) } 1 .. $num_threads;
my $collator = threads -> create ( \&collator );
#queue jobs
$work_q->enqueue(@jobs);
#close queue, so threads will exit when they hit the end of the queue.
#dequeue will return 'undef' rather than blocking.
$work_q->end;
#join all the threads.
$_->join for @workers;
#all threads are finished, so we close the result queue.
#again - so dequeue is undef when empty, rather than just blocking.
$result_q->end;
#reap 'collator' once it's finished.
$collator->join;
print "All done\n";
It's pretty much the same as above, but spawns a list of 'workers' - because then you can end the $work_q, wait for the "workers" to exit (and join) - and then you know there'll be no more results entering the $result_q and can then end that. (And wait for the collator to exit).
forkbefore creating any objects. Especially before creating threads! Your children aren't existing. UsingPOSIX::_exitinstead of$pm->finishcan force them to exit, but that can bite you in the ass. - ikegamifork()and threads? Please lie down and wait until the feeling passes." I'd say, choose either of the methods (don't forget queues if using threads). - zdim