Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #6520 > unrolled thread
| Started by | narke <narkewoody@gmail.com> |
|---|---|
| First post | 2011-05-29 03:53 -0500 |
| Last post | 2011-05-29 22:52 -0500 |
| Articles | 4 — 2 participants |
Back to article view | Back to comp.lang.python
Error: child process close a socket inherited from parent narke <narkewoody@gmail.com> - 2011-05-29 03:53 -0500
Re: Error: child process close a socket inherited from parent narke <narkewoody@gmail.com> - 2011-05-29 08:52 -0500
Re: Error: child process close a socket inherited from parent Chris Torek <nospam@torek.net> - 2011-05-29 23:37 +0000
Re: Error: child process close a socket inherited from parent narke <narkewoody@gmail.com> - 2011-05-29 22:52 -0500
| From | narke <narkewoody@gmail.com> |
|---|---|
| Date | 2011-05-29 03:53 -0500 |
| Subject | Error: child process close a socket inherited from parent |
| Message-ID | <slrniu42cm.2s8.narkewoody@CNZUHNB904.ap.bm.net> |
Hi,
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).
Do you know what's wrong here?
--
Life is the only flaw in an otherwise perfect nonexistence
-- Schopenhauer
narke
[toc] | [next] | [standalone]
| From | narke <narkewoody@gmail.com> |
|---|---|
| Date | 2011-05-29 08:52 -0500 |
| Message-ID | <slrniu4jtb.2s8.narkewoody@CNZUHNB904.ap.bm.net> |
| In reply to | #6520 |
On 2011-05-29, narke <narkewoody@gmail.com> wrote:
> Hi,
>
> 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).
>
> Do you know what's wrong here?
>
>
I forgot to say, it's Python 2.6.4 running on linux 2.6.33
--
Life is the only flaw in an otherwise perfect nonexistence
-- Schopenhauer
narke
[toc] | [prev] | [next] | [standalone]
| From | Chris Torek <nospam@torek.net> |
|---|---|
| Date | 2011-05-29 23:37 +0000 |
| Message-ID | <irulbd081s@news3.newsguy.com> |
| In reply to | #6520 |
In article <slrniu42cm.2s8.narkewoody@CNZUHNB904.ap.bm.net>
narke <narkewoody@gmail.com> 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
[toc] | [prev] | [next] | [standalone]
| From | narke <narkewoody@gmail.com> |
|---|---|
| Date | 2011-05-29 22:52 -0500 |
| Message-ID | <slrniu654a.2m5.narkewoody@cp639.ap.bm.net> |
| In reply to | #6597 |
On 2011-05-29, Chris Torek <nospam@torek.net> wrote:
> In article <slrniu42cm.2s8.narkewoody@CNZUHNB904.ap.bm.net>
> narke <narkewoody@gmail.com> 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.
Chris,
Thanks, you helped to find out a bug in my code.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web