AnyEvent-FDpasser

 view release on metacpan or  search on metacpan

README.pod  view on Meta::CPAN

=head1 DESCRIPTION

This module provides an object oriented interface for passing filehandles between processes. Its primary goals are API simplicity, portability, and reliability. It is suitable for use in non-blocking programs where blocking in even exceptional circum...

This module currently works on BSD4.4-like systems (*BSD, Linux, Mac OS X) where it uses the C<SCM_RIGHTS> ancillary data feature over C<AF_UNIX> sockets, on BSD4.3-like systems (Solaris, IRIX?) where it uses C<msg_accrights> field of C<msghdr> over ...

Note that a passer object is "bidrectional" and you can use the same object to both send and receive filehandles (each side has a separate input and output buffer).

After sending a filehandle, the sending process will automatically destroy it and you shouldn't close it yourself. Forgetting all references to it is what you should do so that the underlying descriptor is actually closed after it is sent. The except...



=over 4

=item my $passer = AnyEvent::FDpasser->new([ fh => <handle(s)>,][ dont_set_nonblocking => 1,][ on_error => $cb->(),])

    ## Both of these are the same
    my $passer = AnyEvent::FDpasser->new;
    my $passer = AnyEvent::FDpasser->new( fh => [ AnyEvent::FDpasser::fdpasser_socketpair ] );

    ## Make sure filehandles are AF_UNIX sockets (BSD) or STREAMS pipes (SysV)
    my $passer = AnyEvent::FDpasser->new( fh => [$fh1, $fh2] );

    ## No i_am_parent or i_am_child required in this case:
    my $passer = AnyEvent::FDpasser->new( fh => $fh, );

When creating a passer objects with two filehandles, it is assumed you want to fork. After you fork you are then supposed call C<< $passer->i_am_parent >> and C<< $passer->i_am_child >>. Creating a passer object with zero filehandles automatically cr...

If you don't plan on forking and instead wish to establish the passing connection via the filesystem, you should only pass one filehandle in. If you only need to support the BSD interface, this filehandle can be created as a normal C<AF_UNIX> socket....

The AnyEvent::FDpasser constructor will set all filehandles to non-blocking mode. You can override this by passing C<dont_set_nonblocking =E<gt> 1,> in. Even though this module will only attempt to send or receive descriptors when the OS has indicate...

An error callback can be passed in with the C<on_error> parameter. If an error happens, the passer object will be shutdown and the callback invoked. C<$@> will be set to the error reason or will be undef in the event of an orderly shutdown.



=item $passer->i_am_parent

If forking the passer object, this method must be called by the parent process after forking.


=item $passer->i_am_child

If forking the passer object, this method must be called by the child process after forking.



=item $passer->push_send_fh($fh[, $cb->()])

After calling C<push_send_fh>, the filehandle passed in will be added to an order-preserving queue. Once the main event loop is entered the filehandle will usually be sent immediately since the peer is a local process. However, if the receiving proce...

In any case, the C<push_send_fh> method will not block. If you wish to perform some action once the socket actually has been sent, you can pass a callback as the second argument to C<push_send_fh>. It will be invoked after the descriptor has been sen...

This method is called C<push_send_fh> instead of, say, C<send_fh> to indicate that it is pushing the filehandle onto the end of a queue. Hopefully it should remind you of the similarly named C<push_write> method in L<AnyEvent::Handle>.


=item $passer->push_recv_fh($cb->($fh))

In order to receive the filehandle, the receiving process calls C<push_recv_fh> and passes it a callback that will be called once one is available. The filehandle will be the first argument to this callback.

Note that you can add multiple callbacks with C<push_recv_fh> to the input queue between returning to the main loop. The callbacks will be invoked in the same order that the filehandles are received (which is the same order that they were sent).

This method is called C<push_recv_fh> instead of, say, C<recv_fh> to indicate that it is pushing a callback onto the end of a queue. Hopefully it should remind you of the similarly named C<push_read> method in L<AnyEvent::Handle>.



=item AnyEvent::FDpasser::fdpasser_socketpair()

This function returns two handles representing both ends of a connected socketpair. On BSD systems it uses C<socketpair(2)> and on SysV systems it uses C<pipe(2)>. Note that this function doesn't work on windows so it's not really useful as a fully-g...

=item $listener_fh = AnyEvent::FDpasser::fdpasser_server($path[, $backlog ])

This function creates a listening node on the filesystem that other processes can connect to and establish FDpasser-capable connections. It is portable between BSD systems where it uses C<AF_UNIX> sockets and SysV systems where it uses the C<connld> ...

=item $passer_fh = AnyEvent::FDpasser::fdpasser_accept($listener_fh)

Given a listener filehandle created with L<AnyEvent::FDpasser::fdpasser_server>, this function accepts and creates a new filehandle suitable for creating an FDpasser object. It is portable between BSD systems where it uses the socket C<accept(2)> sys...

=item $passer_fh = AnyEvent::FDpasser::fdpasser_connect($path)

This function connects to a listening node on the filesystem created with L<AnyEvent::FDpasser::fdpasser_server> and returns a new filehandle suitable for creating an FDpasser object. It is portable between BSD systems where it uses the socket C<conn...

=back




=head1 NOTES

=head2 Userspace buffers

Because the underlying operations only transfer file descriptors, it is undefined whether any data in userspace buffers like IO::Handle or AnyEvent::Handle will have been written to the file descriptor at the time it is transfered. You should always ...

You should remove all IO watchers associated with the descriptor before initiating the transfer because after the descriptor is transfered it will be closed and watchers should always be destroyed before closing their respective filehandles. Also, if...


=head2 Forking

This module itself never calls C<fork()>, but many use-cases of this module involve the application program forking. All the usual things you must worry about when forking an AnyEvent application also apply to this module. In particular, you should e...

Creating a passer object before forking is fine since doing this doesn't install any AnyEvent watchers. Also, using the filesystem with C<AF_UNIX> sockets (or more portably, C<fdpasser_server>, C<fdpasser_accept>, and C<fdpasser_connect>) obviates th...


=head2 Control channels

A useful design is to have a "control channel" associated with each passer that sends over data related to file descriptors being passed. As long as the control channel is a synchronised and ordered queue of messages, each message can indicate how ma...

With both the BSD and SysV APIs it is possible to use the passer filehandle to transfer control data but this module does not support this in order to keep the API simple. However, instead you can use a separate socket connection as your control chan...


=head2 Portability

In order to use the SysV interface, set the C<FDPASSER_SYSV> environment variable when running C<Makefile.PL>:

    $ FDPASSER_SYSV=1 perl Makefile.PL

Currently the default is to always use the BSD interface. It will attempt to figure out which interface is appropriate (BSD4.4 or BSD4.3). Currently Solaris uses 4.3 and everything else uses 4.4. Patches and/or portability reports are welcome.



=head1 FULL DESCRIPTOR TABLES



( run in 0.499 second using v1.01-cache-2.11-cpan-39bf76dae61 )