Commit 19e9fefc authored by Giampaolo Rodolà's avatar Giampaolo Rodolà

Fix Issue 6706: return None on connect() in case of EWOULDBLOCK/ECONNABORTED error.

parent abacccc5
......@@ -211,10 +211,13 @@ any that have been added to the map during asynchronous service) is closed.
.. method:: accept()
Accept a connection. The socket must be bound to an address and listening
for connections. The return value is a pair ``(conn, address)`` where
*conn* is a *new* socket object usable to send and receive data on the
connection, and *address* is the address bound to the socket on the other
end of the connection.
for connections. The return value can be either ``None`` or a pair
``(conn, address)`` where *conn* is a *new* socket object usable to send
and receive data on the connection, and *address* is the address bound to
the socket on the other end of the connection.
When ``None`` is returned it means the connection didn't take place, in
which case the server should just ignore this event and keep listening
for further incoming connections.
.. method:: close()
......@@ -224,6 +227,12 @@ any that have been added to the map during asynchronous service) is closed.
flushed). Sockets are automatically closed when they are
garbage-collected.
.. class:: dispatcher_with_send()
A :class:`dispatcher` subclass which adds simple buffered output capability,
useful for simple clients. For more sophisticated usage use
:class:`asynchat.async_chat`.
.. class:: file_dispatcher()
A file_dispatcher takes a file descriptor or file object along with an
......@@ -240,7 +249,7 @@ any that have been added to the map during asynchronous service) is closed.
socket for use by the :class:`file_dispatcher` class. Availability: UNIX.
.. _asyncore-example:
.. _asyncore-example-1:
asyncore Example basic HTTP client
----------------------------------
......@@ -250,7 +259,7 @@ implement its socket handling::
import asyncore, socket
class http_client(asyncore.dispatcher):
class HTTPClient(asyncore.dispatcher):
def __init__(self, host, path):
asyncore.dispatcher.__init__(self)
......@@ -274,6 +283,45 @@ implement its socket handling::
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
c = http_client('www.python.org', '/')
client = HTTPClient('www.python.org', '/')
asyncore.loop()
.. _asyncore-example-2:
asyncore Example basic echo server
----------------------------------
Here is abasic echo server that uses the :class:`dispatcher` class to accept
connections and dispatches the incoming connections to a handler::
import asyncore
import socket
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
self.send(data)
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_accept(self):
pair = self.accept()
if pair is None:
pass
else:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
handler = EchoHandler(sock)
server = EchoServer('localhost', 8080)
asyncore.loop()
......@@ -350,12 +350,15 @@ class dispatcher:
# XXX can return either an address pair or None
try:
conn, addr = self.socket.accept()
return conn, addr
except socket.error, why:
if why.args[0] == EWOULDBLOCK:
pass
except TypeError:
return None
except socket.error as why:
if why.args[0] in (EWOULDBLOCK, ECONNABORTED):
return None
else:
raise
else:
return conn, addr
def send(self, data):
try:
......
......@@ -35,7 +35,6 @@ given then 8025 is used. If remotehost is not given then `localhost' is used,
and if remoteport is not given, then 25 is used.
"""
# Overview:
#
# This file implements the minimal SMTP protocol as defined in RFC 821. It
......@@ -96,7 +95,6 @@ EMPTYSTRING = ''
COMMASPACE = ', '
def usage(code, msg=''):
print >> sys.stderr, __doc__ % globals()
if msg:
......@@ -104,7 +102,6 @@ def usage(code, msg=''):
sys.exit(code)
class SMTPChannel(asynchat.async_chat):
COMMAND = 0
DATA = 1
......@@ -276,7 +273,6 @@ class SMTPChannel(asynchat.async_chat):
self.push('354 End data with <CR><LF>.<CR><LF>')
class SMTPServer(asyncore.dispatcher):
def __init__(self, localaddr, remoteaddr):
self._localaddr = localaddr
......@@ -299,22 +295,11 @@ class SMTPServer(asyncore.dispatcher):
localaddr, remoteaddr)
def handle_accept(self):
try:
conn, addr = self.accept()
except TypeError:
# sometimes accept() might return None
return
except socket.error, err:
# ECONNABORTED might be thrown
if err[0] != errno.ECONNABORTED:
raise
return
else:
# sometimes addr == None instead of (ip, port)
if addr == None:
return
print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = SMTPChannel(self, conn, addr)
pair = self.accept()
if pair is not None:
conn, addr = pair
print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = SMTPChannel(self, conn, addr)
# API for "doing something useful with the message"
def process_message(self, peer, mailfrom, rcpttos, data):
......@@ -342,7 +327,6 @@ class SMTPServer(asyncore.dispatcher):
raise NotImplementedError
class DebuggingServer(SMTPServer):
# Do something with the gathered message
def process_message(self, peer, mailfrom, rcpttos, data):
......@@ -358,7 +342,6 @@ class DebuggingServer(SMTPServer):
print '------------ END MESSAGE ------------'
class PureProxy(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
lines = data.split('\n')
......@@ -399,7 +382,6 @@ class PureProxy(SMTPServer):
return refused
class MailmanProxy(PureProxy):
def process_message(self, peer, mailfrom, rcpttos, data):
from cStringIO import StringIO
......@@ -478,13 +460,11 @@ class MailmanProxy(PureProxy):
msg.Enqueue(mlist, torequest=1)
class Options:
setuid = 1
classname = 'PureProxy'
def parseargs():
global DEBUGSTREAM
try:
......@@ -541,7 +521,6 @@ def parseargs():
return options
if __name__ == '__main__':
options = parseargs()
# Become nobody
......
......@@ -66,6 +66,9 @@ Core and Builtins
Library
-------
- Issue 6706: asyncore accept() method no longer raises EWOULDBLOCK/ECONNABORTED
on incomplete connection attempt but returns None instead.
- Issue #10266: uu.decode didn't close in_file explicitly when it was given
as a filename. Patch by Brian Brazil.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment