AE Fork Pool reaping problem

Marc Lehmann schmorp at schmorp.de
Sat Apr 8 20:42:11 CEST 2017


On Fri, Apr 07, 2017 at 01:56:53PM +0100, Michael Wright <mjw at methodanalysis.com> wrote:
> Running it like so:
> 
>    $ perl -Ilib ./defuncter.pl
>    child 16065 init
>    child 16065 working
> 
> 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

Hmm, I have a hard time matching the pids from your output to the ps
listing, but fortunately, I can reproduce it here using your test files :)

Anyway, it indeed is caused by loading Mojo::UserAgent, as it (eventually)
loads EV, which installs a SIGCHLD handler. Since nothing then runs the EV
loop, children will not get reaped.

I've thoguht long and hard about this - neither Mojo, nor EV,
AnyEvent::Fork::* or your code can really be blamed here, as they all locally
do the right (and required) thing(s) - the behaviour just cannot be
completely hidden by any one component.

I think the best way to proceed for you in this specific case is to add
this to your worker:

   use Mojo::UserAgent; # atfer this line
   BEGIN { $SIG{CHLD} = 'IGNORE' } # restore the SIGCHLD setting

This has the side effect of breaking EV's child watchers (and CHLD signal
watcher), by taking things into your own hand, but if you don't need these,
this is the way to go.

A safer way would be to declare Mojo::UserAgent not fork-safe and load it
only in "sub init", which increases memory consumption and worker startup
time, which might or might not be an issue for you.

Mojolicuous can't do anything about this, because it doesn't know it is
loaded in the "wrong" process. EV can't do anything about it because of the
same reason, and because it has to install a signal handler before the signal
might be raised. AnyEvent::Fork::** can't do anything about it because it
doesn't know anything about what those modules do.

Well, not quite true - if Mojolicuous used AnyEvent instead of brewing
its own EV-based reactor module, it would likely just work, but that's a
design decision of reinventing the wheel or not.

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\



More information about the anyevent mailing list