RFC: AnyEvent::Handle with two non-duplex filehandles

Marc Lehmann schmorp at schmorp.de
Mon Apr 22 11:10:27 CEST 2013


On Mon, Apr 22, 2013 at 03:37:54PM +1200, Mark Lawrence <nomad at null.net> wrote:
> I wish I only had one handle for reading and writing to ssh, but how do
> you arrange that?

create a socketpair, fork, dup it over stdin and stdout, exec ssh and you
are done. no need for fancy modules either.

> The inter-process communication tools I've seen
> (open(),

I didn't know open returned or required two handles, how do you do that?

> IPC::* etc) all seem to return or require separate in/out

Are you sure they require separate handles? That happens when you pass in
the same handle for stdin and stdout?

I must admit I never used any of the IPC modules that come with perl
because they never seem to do anything useful that I couldn't do better
without them. Maybe it's time to deprecate those, but thats probably just
me :)

> handles. Is there a trick I'm not aware of for combining the child
> process Stdin and Stdout filehandles into one?

A file handle is a perl construct - what counts to ssh is the file
descriptor, and while those are diferent integers for stdin and stdout,
they will happily refer to the same underlying file description (e.g. a
socket or some other full-duplex pipe).

> > I think using weak references or explicit ->destroy calls should take
> > care of these loops without too much effort.
> 
> I think the challenge I am facing is not knowning all of the places I
> should be using ->destroy. However weakening the references (which I
> haven't used here yet) may well sort things out.

You need to destroy when you no longer need the handle, which should
be reaosnably easy to identify (e.g. in on_error, or when you finsihed
talking to the server).

> I'm facing something of a call-back hell due to needing to maintain
> state between events, possibly resulting in lexical variables (i.e.
> filehandles) being passed into multiple anonymous subrefs where I
> assume they are not weak:
> 
>     $state = calculate_state();
>     $whl->push_write(...);
> 
>     $rdl->push_read(line => sub {
>         $state = calculate_state_again();
> 
>         # handle the read, and then push another write...
>         $whl->push_write(...);
>         $rdl->push_read(...);
>     });

If $whl is weak to begin with, it will stay weak inside the close passed
to push_readline as well.

The easy solution that should alwas work is have a wrapper object that
only points to the real object(s) - since nothing inside keeps a reference
to the wrapper, it's DESTROY can unravel the object hierarchy. XML::Parser
uses this for example.

-- 
                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