Re: Error: child process close a socket inherited from parent

Discussion in 'Python' started by Chris Torek, May 30, 2011.

  1. Chris Torek

    Chris Torek Guest

    In article <>
    narke <> wrote:
    >As illustrated in the following simple sample:
    >
    >import sys
    >import os
    >import socket
    >
    >class Server:
    > def __init__(self):
    > self._listen_sock = None
    >
    > def _talk_to_client(self, conn, addr):
    > text = 'The brown fox jumps over the lazy dog.\n'
    > while True:
    > conn.send(text)
    > data = conn.recv(1024)
    > if not data:
    > break
    > conn.close()
    >
    > def listen(self, port):
    > self._listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    > self._listen_sock.bind(('', port))
    > self._listen_sock.listen(128)
    > self._wait_conn()
    >
    > def _wait_conn(self):
    > while True:
    > conn, addr = self._listen_sock.accept()
    > if os.fork() == 0:
    > self._listen_sock.close() # line x
    > self._talk_to_client(conn, addr)
    > else:
    > conn.close()
    >
    >if __name__ == '__main__':
    > Server().listen(int(sys.argv[1]))
    >
    >Unless I comment out the line x, I will get a 'Bad file descriptor'
    >error when my tcp client program (e.g, telnet) closes the connection to
    >the server. But as I understood, a child process can close a unused
    >socket (file descriptor).


    It can.

    >Do you know what's wrong here?


    The problem turns out to be fairly simple.

    The routine listen() forks, and the parent process (with nonzero pid)
    goes into the "else" branch of _wait_conn(), hence closes the newly
    accepted socket and goes back to waiting on the accept() call, which
    is all just fine.

    Meanwhile, the child (with pid == 0) calls close() on the listening
    socket and then calls self._talk_to_client().

    What happens when the client is done and closes his end? Well,
    take a look at the code in _talk_to_client(): it reaches the
    "if not data" clause and breaks out of its loop, and calls close()
    on the accepted socket ... and then returns to its caller, which
    is _wait_conn().

    What does _wait_conn() do next? It has finished "if" branch in
    the "while True:" loops, so it must skip the "else" branch and go
    around the loop again. Which means its very next operation is
    to call accept() on the listening socket it closed just before
    it called self._talk_to_client().

    If that socket is closed, you get an EBADF error raised. If not,
    the child and parent compete for the next incoming connection.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: gmail (figure it out) http://web.torek.net/torek/index.html
     
    Chris Torek, May 30, 2011
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Denon
    Replies:
    1
    Views:
    607
    Saravana [MVP]
    Nov 14, 2003
  2. Iñaki Baz Castillo
    Replies:
    7
    Views:
    952
    Iñaki Baz Castillo
    Jan 12, 2010
  3. Noel Dolan
    Replies:
    0
    Views:
    276
    Noel Dolan
    Jul 18, 2004
  4. 陈云星
    Replies:
    5
    Views:
    489
    陈云星
    Jan 18, 2013
  5. Bitswapper
    Replies:
    5
    Views:
    185
    Prasad, Ramit
    Aug 27, 2013
Loading...

Share This Page