asyncore.loop doesn't terminate when there are no more connections

允我心安 提交于 2019-12-13 20:40:55

问题


I am following some example code to use asyncore here, only having set a timeout value for asyncore.loop as in the following full example:

import smtpd
import asyncore

class CustomSMTPServer(smtpd.SMTPServer):

    def process_message(self, peer, mailfrom, rcpttos, data):
        print 'Receiving message from:', peer
        print 'Message addressed from:', mailfrom
        print 'Message addressed to  :', rcpttos
        print 'Message length        :', len(data)
        return

server = CustomSMTPServer(('127.0.0.1', 1025), None)

asyncore.loop(timeout = 1)

I have expected that a timeout occurs after 1 second, but this is not the case. The code runs much longer for than one second. What am I missing here?


回答1:


The timeout argument to asyncore.loop() is the amount of time the select.select call will wait for data. If there is no data before the timeout runs out it will loop and call select.select again.

Same for the channels idea. This does not mean open sockets but means active asyncore.dispatcher or asynchat.async_chat instances. If you want to stop the loop you will have to call the close() method on ALL instances registered.

In your case server.close() will close the instance/channel and remove it from the asyncore loop. If no more channels are active this loop will then terminate itself.




回答2:


I really do not know if the timeout argument to asyncore.loop() really is meant to timeout the function call asyncore.loop() after the specified time, but here is a receipt to make that function timeout after a specified time (replacing the line with asyncore.loop() in the example code):

import signal

class TimeoutError(Exception): pass

# define the timeout handler
def handler(signum, frame):
    raise TimeoutError()

# set the timeout handler and the signal duration
signal.signal(signal.SIGALRM, handler)
signal.alarm(1)
try:
    asyncore.loop()
except TimeoutError as exc:
    print "timeout"
finally:
    signal.alarm(0)



回答3:


The timeout of asyncore.loop() is the timeout for select().

It is not useful, because when select() timeout, it loops back, see the pseudo code:

while True:
    do_something()
    select(...)
    do_something_else()

If I do simulation with firewall-ed sockets, in my Python 2.7.3 asyncore.loop() timeout 1 minute after no data is received from some socket.

I found very useful to have following method in asyncore.dispatcher "subclass":

def handle_error(self):
    raise

In this way I had "proper" exception dump.

Because I do not wanted to have exception, later I changed it to something like:

def handle_error(self):
    print "Error downloading %s" % self.host
    pass

Now my code works correct, without exception.

I did not found a way to control the timeout.



来源:https://stackoverflow.com/questions/14485528/asyncore-loop-doesnt-terminate-when-there-are-no-more-connections

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!