-
-
Notifications
You must be signed in to change notification settings - Fork 30.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
asyncore's accept() is broken #50955
Comments
An old bad design choice in asyncore is how it forces the user to def handle_accept(self):
conn, addr = self.accept() The documentation itself shows the code above as an example of how an
The right thing to do when one of such events occur is to "return" as no Now, altough handling these kind of conditions is quite easy, the API My patch in attachment tries to solve this problem by defining a new [1] |
@giampaolo it looks as if you meant to attach a patch but didn't! :) If you do attach one could you also supply a modified unit test file with it, thanks. |
Shame on me, it seems I totally forgot to attach the patch. |
giampaolo: did you ever rewrite the patch? For reference to other users: Note the complexity of the two handle_accept implementations in that file; both of them begin: |
Here's a rewriting attempt (not tested). class SomeServer(asyncore.dispatcher):
...
def handle_accept():
conn = self.accept()
if conn is None:
return
else:
sock, addr = conn
...
A completely different approach could be to provide a new "TCPServer" class which deprecates direct accept() method usage. Something like this: class TCPServer(asyncore.dispatcher):
def __init__(self, ip, port, handler, interface='', map=None):
asyncore.dispatcher.__init__(self, map=map)
self.create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
self.bind((ip, port))
self.listen(5)
self.handler = handler
def handle_accept(self):
try:
sock, addr = self.accept()
except TypeError:
return
except socket.error, err:
if err[0] != errno.ECONNABORTED:
raise
return
else:
if addr == None:
return
handler = self.handler(conn, self._map)
def writable(self):
return 0 ...but for some reason I don't like it either. Point is asyncore API design is fundamentally wrong and there's nothing we can do about it unless we break backward compatibility or a brand new "asyncore2" module is written. |
Patch in attachment makes accept() return None in case no connection takes place and modifies the doc to make this very clear, also providing an example on how an asyncore-based server should be properly set-up . |
From the accept() man page: EAGAIN or EWOULDBLOCK
The only way this can happen is if the accept() system call returned 0 in addrlen, which sounds rather strange. I'm not convinced hiding operating system bugs is a good idea. |
Do you propose to let the error raise then? As I said, in a better designed framework the user shouldn't be supposed to call accept() at all, but that's how asyncore is designed. |
As long as these errors are reasonably explainable.
I am talking specifically about the address being None (i.e., a (sock,
Perhaps it's time to add an alternative handle_accepted(sock, addr) |
It might be useful to find whether this is tracked somewhere.
This sounds like a very good idea for 3.2. |
Patch in attachment adds a handled_accepted() method to dispatcher class as recommended by Antoine. |
I'm not an asyncore expert, but I can't see anything wrong with the patch. |
Python 3.2 changes committed in r85220. |
CVE-2010-3492 references this issue. |
Fixed in r86084 (2.7) and r86085 (3.1). |
I do not see this as a security bug so no patch for 2.6 please. (Comment requested from IRC). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: