how to use AnyEvent::Handle on the child of AnyEvent::Run (aka portable_socketpair)?
Marc Lehmann
schmorp at schmorp.de
Wed Nov 20 10:21:08 CET 2013
On Wed, Nov 20, 2013 at 05:56:42PM +1000, Andrew Whatson <whatson at gmail.com> wrote:
> After further investigation, it seems the problem is caused by the
> fact that constructing AnyEvent::Run with an "on_read" parameter
> causes a read watcher for the socketpair to be created *before*
> forking. This watcher then exists in both the parent and child,
> causing some weird behaviour.
Well spotted.
@fulko:
Forking in a program using AnyEvent and then trying to use event handling
in both parent and child is doomed from the beginning, because you never
know who registered which watchers, and they are either active in both
parent and child, or (with many of the more advanced event loops that are
not EV) will not even work. (the FORK section in the AnyEvent manpage goes
into a little bit more detail, as Andrew also pointed out).
The only safe way to use fork from perl is to use something like
Proc::FastSpawn (when threads are involved you need to fork+exec from C
code) or the good old fork+exec (in all other cases). Or in other words,
fork is to start new programs via exec, not for parallel processing.
Trying to do parallel processing with fork is not going to work except in
the most simplest cases in completely controlled conditions (event loop is
known, all of the code is known).
That is, essentially, why I wrote Proc::FastSpawn and
AnyEvent::Fork+submodules, to work around this effective limitation in
(modern) unix.
Using fork seems simple at first (simpler than using e.g. AnyEvent::Fork),
but in the long run, you will only run into problems with this approach.
(if anybody knows of similar modules to AnyEvent::Fork, i.e. ones that
actually create a new process image via exec, then tell me, so I don't
have to advertise my modules all the time :)
> The work-around is to set on_read afterwards:
>
> my $child = AnyEvent::Run->new(cmd => sub { ... });
> $child->on_read(sub { ... });
While this can work in this case, it relies on undocumented behaviour
inside Anyevent::Run, and in general has a very fragile dependency on code
that is generally outside of ones control (for example, AnyEvent, during
intiialisation, might create any number of watchers that will malfunction.
Even if AnyEvent doesn't do it, the event loop itself might. Even if the
event loop might not do it, other modules might. And so on.).
> It seems to me that this behaviour could be considered a bug in
> AnyEvent::Run. The patch to fix it there is straightforward, we just
> move AnyEvent::Handle construction into the parent section after the
> call to fork.
No, it's a design bug in the original program - AnyEvent::Run cannot
ensure that _all_ existing watchers play nicely after fork, and generally
shouldn't need to.
This is really the same problem as calling exit in a forked subprocess and
wondering why things break, or not setting cloexec on file descriptors
(that you might not even know of) and wondering why things break, or
forking from a threaded program and wondering why things break, and so on.
fork should be followed by exec or _exit. Trying to do event processing is
simply doomed, and AnyEvent::Run can not ensure anything.
--
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