Re: Passing file descriptors

From: Josiah Carlson (
Date: 06/10/04

Date: Thu, 10 Jun 2004 00:25:07 -0700

> When I first saw the subject, I was about to point out that you had
> the wrong newsgroup: you want comp.lang.perl.misc
> I see you were talking about something else though.

No perl here.

> Last I checked, you have to use a Unix-domain socket to do this in
> Linux.

No dice...

     [jcarlson@dev jcarlson]$ python
     Traceback (most recent call last):
       File "", line 63, in ?
         ret = fcntl.ioctl(pRead, 1, s)
     IOError: [Errno 22] Invalid argument
     [Errno 14] Bad address
     [jcarlson@dev jcarlson]$

I've tested the data transfer and it works fine.

Using the below modified code, unix domain sockets do not work. Any
other ideas?

  - Josiah

-----cut here-----


# Example of passing an open filedescriptor with Python. Will only work
# on UNIX dialects that support the I_SENDFD and I_RECVFD ioctl() calls.

import fcntl, os, sys, struct, socket

# fork() off!

pid = os.fork()

port = '10001'

if pid != 0:
     # We're in the parent.

     s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
     pWrite, addr = s.accept()

     # Open a file for passing along to child. Use own source code,
     # which is guaranteed to exist. :)

     fileObj = open('./', 'r')

     # ioctl() will only pass raw filedescriptors. Find fd of fileObj.
     fd = fileObj.fileno()

     # Send to the child using ioctl().

         retval = fcntl.ioctl(pWrite, fcntl.I_SENDFD, fd)

         # Should probably check retval rather than just printing it. :)
         print "Parent ioctl() returned %d" % retval
     except Exception, e:
         print e

     # Wait for child to terminate, then exit.
     os.waitpid(pid, 0)

     import time
     # We're in the child.

     pRead = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

     # Create a string representing the strrecvfd structure that ioctl()
     # will return.
     s = struct.pack('iii', 0, 0, 0)

     # Receive filedescriptor. Will block until descriptor is sent.
     ret = fcntl.ioctl(pRead, fcntl.I_RECVFD, s)

     # Unpack the strrecvfd-structure that ioctl() should return.
     # fd is the filedescriptor, uid/gid the user/group id of the
     # sending stream.
     (fd, uid, gid) = struct.unpack('iii', ret)

     # Reopen the filedescriptor as a Python File-object.
     fileObj = os.fdopen(fd, 'r')

     # Example usage: Read file, print the first line.
     lines = fileObj.readlines()
     print lines[0],