Author image Arnar Mar Hrafnkelsson


File::FDpasser - Perl extension for blah blah blah


        use File::FDpasser;

        die "spipe() failed\n" if !defined(@fd);

        $LS=endp_create("/tmp/openserver") || die "endp_create: $!\n";

        $rin = ''; vec($rin,fileno($LS),1) = 1; $timeout=0.5;
        ($nfound,$timeleft) = select($rout=$rin, '', $eout=$rin, $timeout);

        $fh=serv_accept_fh($LS,$uid) || die "serv_accept: $!\n";
        $fh=endp_connect("/tmp/openserver") || die "endp_connect: $!\n";


File::FDpasser is a module for passing open filedescriptors to and from other scripts or even other programs.

An endpoint is just a Filehandle that can be used to send and receive filehandles over. To create two endpoints before forking spipe() is used - it returns two endpoints or undef on failiure.

If the processes are unrelated or can not use spipe() for some reason, it is possible to create a 'server endpoint' in the filesystem by calling endp_create(). That endpoint can be polled for incomming connections similar to how sockets are polled for incomming connection. To accept an incomming connection serv_accept_fh() is used. It returns a filehandle or undef on failiure.

To connect to a server endpoint from a client program endp_connect() is used. It returns a filehandle to an open connection.

Irregardless of how the endpoints were created send_file() is used to send an open filehandle to the process who has other end of the pipe or socket. The first argument to send_file is the connection to send the open handle over. The second argument is the actual handle to send. Similarly recv_fh() is always used to receive an open filehandle. Both return false on failiure.

How does it work

Under BSD derived systems open filedescriptors are passed over unix domain sockets. SysV systems however pass them over streams.

This means to create that under BSD socketpair() is used to create the socket endpoints. While SysV uses pipe() since pipe on SysV creates a bidirectional stream based pipe.

This is all nice and dandy if you are going to fork later on since both child and parent are going to have an endpoint to read from or write to.

endp_create() is used to create a server endpoint that can be polled for incomming connections with poll or select. Under BSD the perl call socket() is used to create a Unix Domain Socket in the filesystem. Under SysV the perl function pipe() is called followed by an XS function that pushes the conn_ld module on one end of the stream pipe and then calles fattach to attach the pipe end to a point in the filesystem.

To connect to a server endpoint in BSD a socket is created (but not bound to any point in the filesystem) and a connect call is made. In SysV a normal open() in perl is made.

The actuall sending of filedescriptors is done with XS functions that under BSD use sendmsg for sending and recvmsg for reciving. SysV uses an ioctl call to send and receive (getmsg is actually a wrapper for receiving the fd - a uid of the connecting process is discarded since it's not reliably avaliable for BSD system too).



perl(1), sendmsg, recvmsg, ioctl, ioctl_list, select, poll. IO::Handle. Advanced Programming in the UNIX Environment, Addison-Wesley, 1992. UNIX Network Programming, Prentice Hall, 1990.