[Patches] [ python-Patches-1736101 ] asyncore should handle also ECONNABORTED in recv

SourceForge.net noreply at sourceforge.net
Wed Jun 13 23:58:25 CEST 2007


Patches item #1736101, was opened at 2007-06-12 23:10
Message generated for change (Comment added) made by billiejoex
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1736101&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Library (Lib)
Group: Python 2.5
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: billiejoex (billiejoex)
Assigned to: Josiah Carlson (josiahcarlson)
Summary: asyncore should handle also ECONNABORTED in recv

Initial Comment:
asyncore should handle also ECONNABORTED in recv in which case handle_close must be called.
The two programs in attachment, an asyncore based echo-server and a simple client application terminating after having sent some data, shows how the server raises an ECONNABORTED exception.
Note that the exception does not occur if server responds immediatly so I used a time.sleep(1) statement to let internal socket perform send() on the remote 'dead' peer.
Having said that it's probable that ECONNABORTED should be handled also in send method.

Hope this helps.

----------------------------------------------------------------------

>Comment By: billiejoex (billiejoex)
Date: 2007-06-13 23:58

Message:
Logged In: YES 
user_id=1357589
Originator: YES

You're right, sorry.

----------------------------------------------------------------------

Comment By: Josiah Carlson (josiahcarlson)
Date: 2007-06-13 23:13

Message:
Logged In: YES 
user_id=341410
Originator: NO

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.


----------------------------------------------------------------------

Comment By: billiejoex (billiejoex)
Date: 2007-06-13 21:03

Message:
Logged In: YES 
user_id=1357589
Originator: YES

Hi, I've seen your patch but it seems to me that it doesn't include
ECONNABORTED handling for send method.

----------------------------------------------------------------------

Comment By: Josiah Carlson (josiahcarlson)
Date: 2007-06-13 02:40

Message:
Logged In: YES 
user_id=341410
Originator: NO

Please see python.org/sf/1736190 for a patch that includes this particular
bugfixe to asyncore, among others.

----------------------------------------------------------------------

Comment By: billiejoex (billiejoex)
Date: 2007-06-12 23:13

Message:
Logged In: YES 
user_id=1357589
Originator: YES

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

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1736101&group_id=5470


More information about the Patches mailing list