how to use AnyEvent::Handle on the child of AnyEvent::Run (aka portable_socketpair)?
Marc Lehmann
schmorp at schmorp.de
Wed Nov 20 16:28:50 CET 2013
On Wed, Nov 20, 2013 at 10:10:06AM -0500, Fulko Hew <fulko.hew at gmail.com> wrote:
> Because Perl threading would force my variable-sharing issues to be
> extremely
> complicated, I wanted to move instead to: a simple, low-count, multi-process
> approach with a simple (JSON) message passing between them.
For me, that's what AnyEvent::Fork::RPC does (JSON is one of the
serialisation formats it supports out of the box. Soon, I'll add CBOR
which should make it even faster).
Here are some examples:
http://pod.tst.eu/http://cvs.schmorp.de/AnyEvent-Fork-RPC/RPC.pm#EXAMPLES
To do event processing in the child, you want the asynchronous backend:
http://pod.tst.eu/http://cvs.schmorp.de/AnyEvent-Fork-RPC/RPC.pm#Example_2_Asynchronous_Backend
> I appreciate the benefits of fork-exec but, to make my application safe,
> isn't there just a simple way of 'undef'ing (in the child),
> anything that AnyEvent or its event loops _might_ have created,
> (if its done early enough)?
No, and even if, it wouldn't actually help:
- some event handlers are required for the event handling itself to work,
these would break (for example, most event loops need an internal I/O
watcher and special action after fork).
- something else might start threads, making fork from perl very difficult.
- some things might need cleanup handlers to be run, most things must not
run their cleanup handler.
While the simple, low-count, multi-process approach is probably doable,
using fork and doing stuff in the child is not it.
No doubt you can make it work in specific cases, when you are extremely
careful and know exactly what you (and the other people whose modules you
use) do. In reality, it's going to end badly sooner or later.
> I find my alternative is to create separate processes for each with
> simple message passing between them. And for code management purposes,
> I'd like to keep it all within a single file.
AnyEvent::Fork supports that, too, as long as that "single file" is your
main program (see AnyEvent::Fork::Template, which lets you fork your
program before you do any event handling and then use the resulting child
or children):
http://pod.tst.eu/http://cvs.schmorp.de/AnyEvent-Fork/Fork/Template.pm
Another option is to keep your subprocess code in a __DATA__ section and
eval'ing it in the subprocesses you create. The AnyEvent::Fork manpage has
an example:
http://pod.tst.eu/http://cvs.schmorp.de/AnyEvent-Fork/Fork.pm#For_stingy_users_put_the_worker_code
> I don't really want to incur the complexity of getting my appropriate
> information passed through to the exec'ed application; or to recreate
> the portable_socketpair communications between my parent and children
> (that seems so easy because it comes with AnyEvent::Run)
> [primarily because I don't understand the details of doing it myself].
AnyEvent::Fork::RPC takes care of the details for you - you won't see
the socketpair. It takes a while to wrap your head around these modules
(simply because they are so different), but I think they are actually
quite simple to use, and if you look at their implementation, they also
add very little overhead to your program.
I know it sounds like advertising, but I've been where you are, I have
felt the pain you felt, and something like AnyEvent::Fork is the solution
that works in the long run. There might be others, but the limited number
of other solutions that I have seen all fall into the fork+fail trap and
only work with trivial programs that don't do event handling or anything
complicated.
--
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