[form fields] fix severe memory leak due to @cached on field.input_name stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 11 Mar 2010 19:16:35 +0100
branchstable
changeset 4871 a34b76593ab2
parent 4870 101858d845f7
child 4872 edfc071d2659
[form fields] fix severe memory leak due to @cached on field.input_name occuring on forms with persistent fields. Has been triggered in 3.6.1 on our public sites because: * the login form use persistent field since 3.6 * it's displayed on every anonymous request * another bug (fixed during the latest mini-sprint) made it also displayed for authenticated user see explanation in code for more detail. moral: be very careful with @cached...
web/formfields.py
--- a/web/formfields.py	Thu Mar 11 19:07:45 2010 +0100
+++ b/web/formfields.py	Thu Mar 11 19:16:35 2010 +0100
@@ -14,7 +14,6 @@
 
 from logilab.mtconverter import xml_escape
 from logilab.common.date import ustrftime
-from logilab.common.decorators import cached
 
 from yams.schema import KNOWN_METAATTRIBUTES
 from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
@@ -189,19 +188,28 @@
         """return the widget instance associated to this field"""
         return self.widget
 
-    # cached is necessary else we get some pb on entity creation : entity.eid is
-    # modified from creation mark (eg 'X') to its actual eid (eg 123), and then
-    # `field.input_name()` won't return the right key anymore if not cached
-    # (first call to input_name done *before* eventual eid affectation).
-    @cached
     def input_name(self, form, suffix=None):
         """return 'qualified name' for this field"""
-        name = self.role_name()
-        if suffix is not None:
-            name += suffix
-        if self.eidparam:
-            return eid_param(name, form.edited_entity.eid)
-        return name
+        # caching is necessary else we get some pb on entity creation :
+        # entity.eid is modified from creation mark (eg 'X') to its actual eid
+        # (eg 123), and then `field.input_name()` won't return the right key
+        # anymore if not cached (first call to input_name done *before* eventual
+        # eid affectation).
+        #
+        # note that you should NOT use @cached else it will create a memory leak
+        # on persistent fields (eg created once for all on a form class) because
+        # of the 'form' appobject argument: the cache will keep growing as new
+        # form are created...
+        try:
+            return form.formvalues[(self, 'input_name')]
+        except KeyError:
+            name = self.role_name()
+            if suffix is not None:
+                name += suffix
+            if self.eidparam:
+                name = eid_param(name, form.edited_entity.eid)
+            form.formvalues[(self, 'input_name')] = name
+            return name
 
     def role_name(self):
         """return <field.name>-<field.role> if role is specified, else field.name"""