[New-bugs-announce] [issue6589] smtpd.SMTPServer can cause asyncore.loop to enter infinite event loop

Casey McGinty report at bugs.python.org
Tue Jul 28 05:59:58 CEST 2009


New submission from Casey McGinty <casey.mcginty at gmail.com>:

When subclass of smtpd.SMTPServer, it is possible the get asyncore.loop
to enter an infinite loop where the following output is shown:

.....
warning: unhandled write event
warning: unhandled read event
warning: unhandled write event
warning: unhandled read event
warning: unhandled write event
warning: unhandled read event
warning: unhandled write event
warning: unhandled read event
warning: unhandled write event
warning: unhandled read event
warning: unhandled write event
warning: unhandled read event
....

To reproduce:
1) Init SMTPServer class instance inside of Thread class and call
asyncore.loop()
2) Init second SMTPServer class instance from a second Thread class,
binding to the same address and port. The SMTPServer instance will raise
an exception that socket cannot bind to the port in use. The socket
exception must be caught at some level, and the program execution
allowed to continue.
3) First SMTPServer thread will enter infinite event loop.


Analysis:
When the exception is raised in the second SMTPServer instance, the new
instance has already registered itself with the asyncore library (ex:
'asyncore.dispatcher.__init__(self)'). There is no code in the
SMTPServere.__init__ method that catches the exception raised, caused by
the failed bind attempt. After the exception is caught, the first thread
continues to run, but asyncore is in an invalid state because it still
has the registration of the second SMTPServer instance that never completed.

Workaround and Proposed Fix:
A viable workaround seems to be catching the raised exception in
__init__ method of the SMTPServer subclass, and call self.close() before
re-raising the exception:

class MySmtpServer( smtpd.SMTPServer, object ):
   def __init__( self, **kwargs ):
      try:
         super( _SmtpSink, self).__init__(**kwargs)
      except Exception as e:
         self.close()   # cleanup asyncore after failure
         raise

For a long term fix, I would recommend performing the
asyncore.dispatcher.close() method call in the SMTPServer.__init__() method.

----------
components: Library (Lib)
messages: 91002
nosy: cmcginty
severity: normal
status: open
title: smtpd.SMTPServer can cause asyncore.loop to enter infinite event loop
versions: Python 2.6

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue6589>
_______________________________________


More information about the New-bugs-announce mailing list