fix: broken retry loop would break connection management

The retry loop would release connection that would get
re-released upon ``finally`` clause. In consequence, an
exception would be cast.

Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Valentin Lab 2015-11-25 14:39:56 +08:00 committed by Nicolas Sebrecht
parent 573d55827f
commit f2ca4217c6
2 changed files with 34 additions and 27 deletions

View File

@ -72,11 +72,7 @@ class GmailFolder(IMAPFolder):
(probably severity MESSAGE) if e.g. no message with (probably severity MESSAGE) if e.g. no message with
this UID could be found. this UID could be found.
""" """
imapobj = self.imapserver.acquireconnection() data = self._fetch_from_imap(str(uid), 2)
try:
data = self._fetch_from_imap(imapobj, str(uid), 2)
finally:
self.imapserver.releaseconnection(imapobj)
# data looks now e.g. # data looks now e.g.
#[('320 (X-GM-LABELS (...) UID 17061 BODY[] {2565}','msgbody....')] #[('320 (X-GM-LABELS (...) UID 17061 BODY[] {2565}','msgbody....')]

View File

@ -282,11 +282,7 @@ class IMAPFolder(BaseFolder):
this UID could be found. this UID could be found.
""" """
imapobj = self.imapserver.acquireconnection() data = self._fetch_from_imap(str(uid), 2)
try:
data = self._fetch_from_imap(imapobj, str(uid), 2)
finally:
self.imapserver.releaseconnection(imapobj)
# data looks now e.g. [('320 (UID 17061 BODY[] # data looks now e.g. [('320 (UID 17061 BODY[]
# {2565}','msgbody....')] we only asked for one message, # {2565}','msgbody....')] we only asked for one message,
@ -680,7 +676,7 @@ class IMAPFolder(BaseFolder):
return uid return uid
def _fetch_from_imap(self, imapobj, uids, retry_num=1): def _fetch_from_imap(self, uids, retry_num=1):
"""Fetches data from IMAP server. """Fetches data from IMAP server.
Arguments: Arguments:
@ -690,22 +686,37 @@ class IMAPFolder(BaseFolder):
Returns: data obtained by this query.""" Returns: data obtained by this query."""
imapobj = self.imapserver.acquireconnection()
try:
query = "(%s)"% (" ".join(self.imap_query)) query = "(%s)"% (" ".join(self.imap_query))
fails_left = retry_num # retry on dropped connection fails_left = retry_num ## retry on dropped connection
while fails_left: while fails_left:
try: try:
imapobj.select(self.getfullname(), readonly = True) imapobj.select(self.getfullname(), readonly = True)
res_type, data = imapobj.uid('fetch', uids, query) res_type, data = imapobj.uid('fetch', uids, query)
fails_left = 0 break
except imapobj.abort as e: except imapobj.abort as e:
fails_left -= 1
# self.ui.error() will show the original traceback
if fails_left <= 0:
message = ("%s, while fetching msg %r in folder %r."
" Max retry reached (%d)"%
(e, uids, self.name, retry_num))
severity = OfflineImapError.ERROR.MESSAGE
raise OfflineImapError(message,
OfflineImapError.ERROR.MESSAGE)
# Release dropped connection, and get a new one # Release dropped connection, and get a new one
self.imapserver.releaseconnection(imapobj, True) self.imapserver.releaseconnection(imapobj, True)
imapobj = self.imapserver.acquireconnection() imapobj = self.imapserver.acquireconnection()
self.ui.error(e, exc_info()[2]) self.ui.error("%s. While fetching msg %r in folder %r."
fails_left -= 1 " Retrying (%d/%d)"%
# self.ui.error() will show the original traceback (e, uids, self.name, retry_num - fails_left, retry_num))
if not fails_left: finally:
raise e # The imapobj here might be different than the one created before
# the ``try`` clause. So please avoid transforming this to a nice
# ``with`` without taking this into account.
self.imapserver.releaseconnection(imapobj)
if data == [None] or res_type != 'OK': if data == [None] or res_type != 'OK':
#IMAP server says bad request or UID does not exist #IMAP server says bad request or UID does not exist
severity = OfflineImapError.ERROR.MESSAGE severity = OfflineImapError.ERROR.MESSAGE