Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'kazuho/issues/fix-wait-with-timeout'

  • Loading branch information...
commit e352032982b830a822278c3066c7485f8cabca84 2 parents bc0280b + dcec28a
@kazuho authored
Showing with 28 additions and 24 deletions.
  1. +20 −16 lib/Parallel/Prefork.pm
  2. +8 −8 t/06-wait-all-children-with-timeout.t
View
36 lib/Parallel/Prefork.pm
@@ -192,28 +192,32 @@ sub wait_all_children {
my ($self, $timeout) = @_;
$self->{_no_adjust_until} = undef;
- my $call_wait = sub {
- my $blocking = shift;
- if (my ($pid) = $self->_wait($blocking)) {
- if (delete $self->{worker_pids}{$pid}) {
- $self->_on_child_reap($pid, $?);
+ my $wait_loop = sub {
+ while (%{$self->{worker_pids}}) {
+ if (my ($pid) = $self->_wait(1)) {
+ if (delete $self->{worker_pids}{$pid}) {
+ $self->_on_child_reap($pid, $?);
+ }
}
}
};
if ($timeout) {
- # the strategy is to use waitpid + sleep that gets interrupted by SIGCHLD
- # but since there is a race condition bet. waitpid and sleep, the argument
- # to sleep should be set to a small number (and we use 1 second).
- my $start_at = [Time::HiRes::gettimeofday];
- while ($self->num_workers != 0 && Time::HiRes::tv_interval($start_at) < $timeout) {
- $call_wait->(0);
- sleep 1;
- }
+ local $@;
+ my $is_timeout = 0;
+ eval {
+ local $SIG{ALRM} = sub {
+ $is_timeout = 1;
+ die "timeout";
+ };
+ alarm($timeout);
+ $wait_loop->();
+ alarm(0);
+ };
+ die $@
+ if $@ && ! $is_timeout;
} else {
- while ($self->num_workers != 0) {
- $call_wait->(1);
- }
+ $wait_loop->();
}
return $self->num_workers;
}
View
16 t/06-wait-all-children-with-timeout.t
@@ -11,7 +11,7 @@ use Parallel::Prefork;
my $reaped = 0;
my $pm = Parallel::Prefork->new({
- max_workers => 3,
+ max_workers => 30,
fork_delay => 0,
on_child_reap => sub {
$reaped++;
@@ -30,27 +30,27 @@ until ($pm->signal_received) {
open my $fh, '+<', $filename
or die "failed to open temporary file: $filename: ";
flock $fh, LOCK_EX;
- sysread $fh, my $c, 10;
- $c++;
+ sysread $fh, my $worker_count, 10;
+ $worker_count++;
seek $fh, 0, 0;
- syswrite $fh, $c, length($c);
+ syswrite $fh, $worker_count, length($worker_count);
flock $fh, LOCK_UN;
close $fh;
my $rcv = 0;
local $SIG{TERM} = sub { $rcv++ };
- if ($c == $pm->max_workers) {
+ if ($worker_count == $pm->max_workers) {
kill 'TERM', $manager_pid;
}
- sleep(100) while $rcv < $c;
+ sleep(100) while $rcv * 10 < $worker_count;
$pm->finish;
}
-is $pm->wait_all_children(1), 2, 'should reap one worker.';
+is $pm->wait_all_children(1), 20, 'should reap one worker.';
$pm->signal_all_children('TERM');
-is $pm->wait_all_children(1), 1, 'should reap one worker.';
+is $pm->wait_all_children(1), 10, 'should reap one worker.';
$pm->signal_all_children('TERM');
$pm->wait_all_children();
is $pm->num_workers, 0, 'all workers reaped.';
Please sign in to comment.
Something went wrong with that request. Please try again.