[notification] avoid leaking cnxsets (closes #3243810) stable
authorJulien Cristau <julien.cristau@logilab.fr>
Wed, 23 Oct 2013 14:18:58 +0200
branchstable
changeset 9305 f7a738afc295
parent 9298 eff262f5ec3f
child 9306 8ab0e601d418
[notification] avoid leaking cnxsets (closes #3243810) When sending notifications, we get each recipient as either an email address or a CWUser. In the latter case, we create a temporary session for that user and use it to send the mail. However, if we later decided to not send the mail after all, we'd leak the session and its cnxset. Add a try block inside the loop to make sure the temporary sessions are closed properly.
sobjects/notification.py
--- a/sobjects/notification.py	Thu Oct 17 16:30:53 2013 +0200
+++ b/sobjects/notification.py	Wed Oct 23 14:18:58 2013 +0200
@@ -128,26 +128,34 @@
             # since the same view (eg self) may be called multiple time and we
             # need a fresh stream at each iteration, reset it explicitly
             self.w = None
-            # XXX call render before subject to set .row/.col attributes on the
-            #     view
             try:
-                content = self.render(row=0, col=0, **kwargs)
-                subject = self.subject()
-            except SkipEmail:
-                continue
-            except Exception as ex:
-                # shouldn't make the whole transaction fail because of rendering
-                # error (unauthorized or such) XXX check it doesn't actually
-                # occurs due to rollback on such error
-                self.exception(str(ex))
-                continue
-            msg = format_mail(self.user_data, [emailaddr], content, subject,
-                              config=self._cw.vreg.config, msgid=msgid, references=refs)
-            yield [emailaddr], msg
-            if isinstance(something, Entity):
-                self._cw.commit()
-                self._cw.close()
-                self._cw = req
+                # XXX call render before subject to set .row/.col attributes on the
+                #     view
+                try:
+                    content = self.render(row=0, col=0, **kwargs)
+                    subject = self.subject()
+                except SkipEmail:
+                    continue
+                except Exception as ex:
+                    # shouldn't make the whole transaction fail because of rendering
+                    # error (unauthorized or such) XXX check it doesn't actually
+                    # occurs due to rollback on such error
+                    self.exception(str(ex))
+                    continue
+                msg = format_mail(self.user_data, [emailaddr], content, subject,
+                                  config=self._cw.vreg.config, msgid=msgid, references=refs)
+                yield [emailaddr], msg
+            except:
+                if isinstance(something, Entity):
+                    self._cw.rollback()
+                raise
+            else:
+                if isinstance(something, Entity):
+                    self._cw.commit()
+            finally:
+                if isinstance(something, Entity):
+                    self._cw.close()
+                    self._cw = req
         # restore language
         req.set_language(origlang)