AE Fork Pool reaping problem
Michael Wright
mjw at methodanalysis.com
Fri Apr 7 20:04:53 CEST 2017
On Tue, Mar 21, 2017 at 10:41 AM, Marc Lehmann <schmorp at schmorp.de> wrote:
>
> Hi!
>
> On Wed, Mar 15, 2017 at 11:50:03AM +0000, Michael Wright <mjw at methodanalysis.com> wrote:
> > I've been using AnyEvent::Fork::Pool for a while now in a Mojolicious
> > server environment, and it works well, but I recently introduced retirement
> > of worker processes after a certain number of jobs, and discovered this
> > results in zombies.
> >
> > Not every retirement does, some are clearly reaped fine, and the ratio
> > of defunct processes to retirements does vary quite a bit (no clue
> > why / according to what), but there are a lot.
> >
> > After requesting retirement the child receives and completes remaining
> > jobs, andthe worker return value of the last job, is received fine by the
> > parent, a new worker is spawned, it's just that the old process is still
> > there, some of the time.
> >
> > Defunct process never result from the worker pool spinning down
> > processes because it is idle, only ever when workers request to be retired.
> >
> > Any ideas on what might be the problem?
>
> What is the parent process of the zombie (use ps to find out)? If it's
> one of the processes forked by AnyEvent::Fork, then you have to find out
> why the kernel doesn't reap them - AnyEvent::Fork sets SIGCHLD to IGNORE,
> which means automatic reaping of zombies, but if you take over the process
> itself (using ->run), then SIGCHLD is restored to the previous value, and
> your code would be responsible for reaping children for example. Likewise
> if e.g. SIGCHLD is blocked.
>
> As long as the parent is one of AnyEvent::Fork's template processes or the
> template process has exited, there is no way you should get zombies unless
> your own code somehow enables it.
Hi, thank you for your reply, I've just been revisiting this issue and trying
to create a minimal example, and I've come up with this 'defuncter.pl':
#!/usr/bin/perl
use strict;
use warnings;
use EV;
use AnyEvent;
use AnyEvent::Fork;
use AnyEvent::Fork::Pool;
#sleep 2;
my $worker_pool_template = AnyEvent::Fork->new->require('Worker');
my $pool = $worker_pool_template->AnyEvent::Fork::Pool::run(
'Worker::work',
'init' => 'Worker::init',
'max' => 100,
'idle' => 10,
'load' => 1,
'start' => 2,
'stop' => 1,
);
$pool->('bar', sub { print "child $_[0] parent $$ callback\n"; });
my $w = AnyEvent->condvar;
$w->recv;
And this 'lib/Worker.pm':
package Worker;
use strict;
use warnings;
use Mojo::UserAgent;
sub init {
print "child $$ init\n";
}
sub work {
print "child $$ working\n";
#sleep 2;
print "child $$ done\n";
return $$;
}
1;
Running it like so:
$ perl -Ilib ./defuncter.pl
child 16065 init
child 16065 working
child 16065 done
child 16065 parent 16062 callback
child 16066 init
child 16067 init
child 16068 init
child 16069 init
child 16070 init
child 16071 init
child 16072 init
child 16073 init
child 16074 init
child 16075 init
It generates one defunct process:
$ ps auxw|grep -E 'Worker|defuncter'
mjw 16150 0.2 0.1 36544 6916 pts/5 S+ 13:17 0:00
perl -Ilib ./defuncter.pl
mjw 16153 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16154 0.0 0.0 0 0 pts/5 Z+ 13:17 0:00
[Worker::work of] <defunct>
mjw 16155 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16156 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16157 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16158 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16159 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16160 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16161 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16162 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16175 0.0 0.5 90588 23660 pts/5 S+ 13:17 0:00
Worker::work of 16150
mjw 16198 0.0 0.0 12728 2292 pts/3 S+ 13:17 0:00
grep -E Worker|defuncter
$
If I remove the "use Mojo::UserAgent;", the problem does not present.
If I uncomment either of the sleep statements, the problem does not present.
Perhaps in light of this it's more a Mojolicious issue and this isn't the right
place for the discussion any more, but I thought I'd see what you thought.
More information about the anyevent
mailing list