Re: Passing file descriptors

From: Josiah Carlson (jcarlson_at_uci.edu)
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 fdpass.py
     Traceback (most recent call last):
       File "fdpass.py", 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-----

#!/usr/pd/bin/python
#
# fdpass.py

#
# 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)
     s.bind(port)
     s.listen(1)
     pWrite, addr = s.accept()

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

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

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

     # Send to the child using ioctl().
     try:

         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)
     sys.exit(0)

else:
     import time
     time.sleep(1)
     # We're in the child.

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

     # 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],
     sys.exit(0)



Relevant Pages

  • 9.1 coredump
    ... 462986 data packets ... linux: pid 1069: syscall pipe2 not implemented ...
    (freebsd-stable)
  • Re: single daemon startup
    ... its pid to file ..). ... just to humour you - daemon performs a function similar to ... Linux's "abstract namespace" for unix domain sockets. ...
    (comp.unix.programmer)
  • new tools: linux pid exhaustion scanner, tcp/ip handshake scanner
    ... I have two new security scanning tools, ... Decloak is a "pID exhaustion" scanner for Linux. ... brute-forcing a handshake on every port. ...
    (Pen-Test)
  • Re: sbcl run-program "/bin/sh"
    ... can't access tty; job control turned off ... [And, as you say, not at all on Linux.] ... int stdin, int stdout, int stderr) ... pid_t pid; ...
    (comp.lang.lisp)
  • Re: [opensuse] Re: Systemd: a foolish design making distros into lemmings.
    ... EVERYTHING is wrong with logind being part of PID 1. ... You obviously have no clue about the Unix design principles that have made *nix operating systems THE CHOICE for the overwhelming majority of the internet, and over 99.9% of the supercomputers on the planet. ... Unix and Linux have been multiseat since the beginning of each. ...
    (SuSE)