Charles-François Natali <neolo...@free.fr> added the comment:
> This does not seem to work.
Yes, the proposed fix is buggy: the solution is to drain the output
buffer, guarding against recursive calls between send() and
handle_close() (patch attached).
> Note that after the first 'handle_close' has been printed, there are
> no 'handle_write' printed, which indicates that the operating system
> (here linux) states that the socket is not writable.
That's because you're closing the socket, whereas the original report
is dealing with half-shutdown connections.
Try this:
"""
class Reader(asyncore.dispatcher):
def __init__(self, sock):
asyncore.dispatcher.__init__(self, sock)
+ self.shutdown = False
def writable(self):
return False
def handle_read(self):
self.recv(64)
- self.close()
+ if not self.shutdown:
+ self.shutdown = True
+ self.socket.shutdown(socket.SHUT_WR)
class Writer(asyncore.dispatcher_with_send):
def __init__(self, address):
"""
This will behave as expected.
Calling socket.shutdown(socket.SHUT_WR) means that you won't send any
more data, but that you're still ready to receive: it results in a FIN
being sent to the remote endpoint, which will receive EOF on recv().
But subsequent send() from the remote endpoint will still succeed.
Whereas with socket.close(), you not only shut down your sending part,
but you also signify that you don't want to receive data any more: a
FIN will be sent immediately to the remote endpoint, and on subsequent
send() from the remote endpoint, a RST will be returned, which will
result in EPIPE (or, in there was data in the receive socket buffer
when the local endpoint was closed, a RST will be sent directly,
resulting in ECONNRESET).
I still need to write a test.
----------
keywords: +patch
Added file: http://bugs.python.org/file23552/asyncore_drain.diff
_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue12498>
_______________________________________
diff --git a/Lib/asyncore.py b/Lib/asyncore.py
--- a/Lib/asyncore.py
+++ b/Lib/asyncore.py
@@ -535,6 +535,7 @@
num_sent = 0
num_sent = dispatcher.send(self, self.out_buffer[:512])
self.out_buffer = self.out_buffer[num_sent:]
+ return num_sent
def handle_write(self):
self.initiate_send()
@@ -548,6 +549,15 @@
self.out_buffer = self.out_buffer + data
self.initiate_send()
+ def handle_close(self):
+ if not self.closing:
+ self.closing = True
+ # try to drain the output buffer
+ while self.writable() and self.initiate_send() > 0:
+ pass
+ self.close()
+
+
# ---------------------------------------------------------------------------
# used for debugging.
# ---------------------------------------------------------------------------
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com