idle: protect all calls to imapobj.noop() (coonection might be dropped)

Some code refactoring.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-09-13 04:41:31 +02:00
parent bdfec8d2da
commit dbcfc0b173

View File

@ -86,22 +86,22 @@ class IMAPServer(object):
self.usessl = repos.getssl() self.usessl = repos.getssl()
self.useipv6 = repos.getipv6() self.useipv6 = repos.getipv6()
if self.useipv6 == True: if self.useipv6 is True:
self.af = socket.AF_INET6 self.af = socket.AF_INET6
elif self.useipv6 == False: elif self.useipv6 is False:
self.af = socket.AF_INET self.af = socket.AF_INET
else: else:
self.af = socket.AF_UNSPEC self.af = socket.AF_UNSPEC
self.hostname = \ self.hostname = None if self.preauth_tunnel else repos.gethost()
None if self.preauth_tunnel else repos.gethost()
self.port = repos.getport() self.port = repos.getport()
if self.port == None: if self.port is None:
self.port = 993 if self.usessl else 143 self.port = 993 if self.usessl else 143
self.sslclientcert = repos.getsslclientcert() self.sslclientcert = repos.getsslclientcert()
self.sslclientkey = repos.getsslclientkey() self.sslclientkey = repos.getsslclientkey()
self.sslcacertfile = repos.getsslcacertfile() self.sslcacertfile = repos.getsslcacertfile()
if self.sslcacertfile is None: if self.sslcacertfile is None:
self.__verifycert = None # disable cert verification self.__verifycert = None # Disable cert verification.
# This way of working sucks hard...
self.fingerprint = repos.get_ssl_fingerprint() self.fingerprint = repos.get_ssl_fingerprint()
self.tlslevel = repos.gettlslevel() self.tlslevel = repos.gettlslevel()
self.sslversion = repos.getsslversion() self.sslversion = repos.getsslversion()
@ -671,7 +671,8 @@ class IMAPServer(object):
threads = [] threads = []
for i in range(numconnections): for i in range(numconnections):
self.ui.debug('imap', 'keepalive: processing connection %d of %d'% (i, numconnections)) self.ui.debug('imap', 'keepalive: processing connection %d of %d'%
(i, numconnections))
if len(self.idlefolders) > i: if len(self.idlefolders) > i:
# IDLE thread # IDLE thread
idler = IdleThread(self, self.idlefolders[i]) idler = IdleThread(self, self.idlefolders[i])
@ -805,12 +806,27 @@ class IdleThread(object):
while in IDLE mode, b) we get an Exception (e.g. on dropped while in IDLE mode, b) we get an Exception (e.g. on dropped
connections, or c) the standard imaplib IDLE timeout of 29 connections, or c) the standard imaplib IDLE timeout of 29
minutes kicks in.""" minutes kicks in."""
result, cb_arg, exc_data = args result, cb_arg, exc_data = args
if exc_data is None and not self.stop_sig.isSet(): if exc_data is None and not self.stop_sig.isSet():
# No Exception, and we are not supposed to stop: # No Exception, and we are not supposed to stop:
self.needsync = True self.needsync = True
self.stop_sig.set() # Continue to sync. self.stop_sig.set() # Continue to sync.
def noop(imapobj):
"""Factorize the noop code."""
try:
# End IDLE mode with noop, imapobj can point to a dropped conn.
imapobj.noop()
except imapobj.abort:
self.ui.warn('Attempting NOOP on dropped connection %s'%
imapobj.identifier)
self.parent.releaseconnection(imapobj, True)
else:
self.parent.releaseconnection(imapobj)
while not self.stop_sig.isSet(): while not self.stop_sig.isSet():
self.needsync = False self.needsync = False
@ -837,17 +853,9 @@ class IdleThread(object):
else: else:
self.ui.warn("IMAP IDLE not supported on server '%s'." self.ui.warn("IMAP IDLE not supported on server '%s'."
"Sleep until next refresh cycle."% imapobj.identifier) "Sleep until next refresh cycle."% imapobj.identifier)
imapobj.noop() noop(imapobj) #XXX: why?
self.stop_sig.wait() # self.stop() or IDLE callback are invoked. self.stop_sig.wait() # self.stop() or IDLE callback are invoked.
try: noop(imapobj)
# End IDLE mode with noop, imapobj can point to a dropped conn.
imapobj.noop()
except imapobj.abort:
self.ui.warn('Attempting NOOP on dropped connection %s'%
imapobj.identifier)
self.parent.releaseconnection(imapobj, True)
else:
self.parent.releaseconnection(imapobj)
if self.needsync: if self.needsync:
# Here not via self.stop, but because IDLE responded. Do # Here not via self.stop, but because IDLE responded. Do