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."""
query = "(%s)"% (" ".join(self.imap_query)) imapobj = self.imapserver.acquireconnection()
fails_left = retry_num # retry on dropped connection try:
while fails_left: query = "(%s)"% (" ".join(self.imap_query))
try: fails_left = retry_num ## retry on dropped connection
imapobj.select(self.getfullname(), readonly = True) while fails_left:
res_type, data = imapobj.uid('fetch', uids, query) try:
fails_left = 0 imapobj.select(self.getfullname(), readonly = True)
except imapobj.abort as e: res_type, data = imapobj.uid('fetch', uids, query)
# Release dropped connection, and get a new one break
self.imapserver.releaseconnection(imapobj, True) except imapobj.abort as e:
imapobj = self.imapserver.acquireconnection() fails_left -= 1
self.ui.error(e, exc_info()[2]) # self.ui.error() will show the original traceback
fails_left -= 1 if fails_left <= 0:
# self.ui.error() will show the original traceback message = ("%s, while fetching msg %r in folder %r."
if not fails_left: " Max retry reached (%d)"%
raise e (e, uids, self.name, retry_num))
severity = OfflineImapError.ERROR.MESSAGE
raise OfflineImapError(message,
OfflineImapError.ERROR.MESSAGE)
# Release dropped connection, and get a new one
self.imapserver.releaseconnection(imapobj, True)
imapobj = self.imapserver.acquireconnection()
self.ui.error("%s. While fetching msg %r in folder %r."
" Retrying (%d/%d)"%
(e, uids, self.name, retry_num - fails_left, retry_num))
finally:
# 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