Issue 1736101: asyncore should handle also ECONNABORTED in recv (original) (raw)
client
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 21)) s.send("sumthin")
server
import asyncore, asynchat import socket import time
class Handler(asynchat.async_chat):
def __init__(self, server, sock, addr):
asynchat.async_chat.__init__(self, sock)
self.set_terminator("\n")
self.data = ""
self.respond("Hey there!\r\n")
def respond(self, data):
print "->" + data
time.sleep(1)
self.push(data)
def collect_incoming_data(self, data):
print "<-" + data
self.data = self.data + data
def found_terminator(self):
self.respond(self.data)
self.data = ''
def handle_close(self):
remote_ip, remote_port = self.socket.getpeername()
print "%s:%s disconnected" %(remote_ip, remote_port)
self.close()
def handle_error(self):
raise
class Server(asyncore.dispatcher):
def __init__(self, address):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(address)
self.listen(5)
def handle_accept(self):
conn, addr = self.accept()
Handler(self, conn, addr)
address = ('', 21) Server(address) print "server ready." asyncore.loop()
proposed patch
--- line 55
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
ENOTCONN, ESHUTDOWN, EINTR, EISCONN, errorcode
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
ENOTCONN, ESHUTDOWN, EINTR, EISCONN, ECONNABORTED, errorcode
--- line 329 def send(self, data): try: result = self.socket.send(data) return result except socket.error, why: if why[0] == EWOULDBLOCK: return 0
elif why[0] == ECONNABORTED:
self.handle_close()
return 0 else: raise return 0
--- line 340 def recv(self, buffer_size): try: data = self.socket.recv(buffer_size) if not data: # a closed connection is indicated by signaling # a read condition, and having recv() return 0. self.handle_close() return '' else: return data except socket.error, why: # winsock sometimes throws ENOTCONN
if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED]: self.handle_close() return '' else: raise
Re-read the patch. In particular...
@@ -333,9 +349,11 @@ except socket.error, why: if why[0] == EWOULDBLOCK: return 0
elif why[0] in (ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED):
self.handle_close()
return 0
That is added handling for all four potential errors in send.