diff --git a/product/ERP5Type/dynamic/lazy_class.py b/product/ERP5Type/dynamic/lazy_class.py
index 61824706a86334803521d6b60029bf332bfd405e..997730cc3d68bc2f4bcfe7efd3715cb3862b6d04 100644
--- a/product/ERP5Type/dynamic/lazy_class.py
+++ b/product/ERP5Type/dynamic/lazy_class.py
@@ -18,8 +18,14 @@ ERP5BaseBroken = type('ERP5BaseBroken', (Broken, ERP5Base), dict(x
   for x in PersistentBroken.__dict__.iteritems()
   if x[0] not in ('__dict__', '__module__', '__weakref__')))
 
-class GhostPortalType(ERP5Base): #SimpleItem
+
+class GhostBaseMetaClass(ExtensionClass):
+  """
+  Generate classes that will be used as bases of portal types to
+  mark portal types as non-loaded and to force loading it.
   """
+
+  ghost_doc = """\
   Ghost state for a portal type class that is not loaded.
 
   When an instance of this portal type class is loaded (a new object is
@@ -31,33 +37,42 @@ class GhostPortalType(ERP5Base): #SimpleItem
   load, a portal type class does not use GhostPortalType in its __bases__
   anymore.
   """
-  def __init__(self, *args, **kw):
-    self.__class__.loadClass()
-    getattr(self, '__init__')(*args, **kw)
-
-  def __getattribute__(self, attr):
-    """
-    This is only called once to load the class.
-    Because __bases__ is changed, the behavior of this object
-    will change after the first call.
-    """
-    # Class must be loaded if '__of__' is requested because otherwise,
-    # next call to __getattribute__ would lose any acquisition wrapper.
-    if attr in ('__class__',
-                '__getnewargs__',
-                '__getstate__',
-                '__dict__',
-                '__module__',
-                '__name__',
-                '__repr__',
-                '__str__') or attr[:3] in ('_p_', '_v_'):
-      return super(GhostPortalType, self).__getattribute__(attr)
-    #LOG("ERP5Type.Dynamic", BLATHER,
-    #    "loading attribute %s.%s..." % (name, attr))
-    self.__class__.loadClass()
-    return getattr(self, attr)
-
-class PortalTypeMetaClass(ExtensionClass):
+  def __init__(cls, name, bases, dictionary):
+    super(GhostBaseMetaClass, cls).__init__(name, bases, dictionary)
+
+    def __init__(self, *args, **kw):
+      self.__class__.loadClass()
+      getattr(self, '__init__')(*args, **kw)
+
+    def __getattribute__(self, attr):
+      """
+      This is only called once to load the class.
+      Because __bases__ is changed, the behavior of this object
+      will change after the first call.
+      """
+      # Class must be loaded if '__of__' is requested because otherwise,
+      # next call to __getattribute__ would lose any acquisition wrapper.
+      if attr in ('__class__',
+                  '__getnewargs__',
+                  '__getstate__',
+                  '__dict__',
+                  '__module__',
+                  '__name__',
+                  '__repr__',
+                  '__str__') or attr[:3] in ('_p_', '_v_'):
+        return super(cls, self).__getattribute__(attr)
+      #LOG("ERP5Type.Dynamic", BLATHER,
+      #    "loading attribute %s.%s..." % (name, attr))
+      self.__class__.loadClass()
+      return getattr(self, attr)
+
+    cls.__getattribute__ = __getattribute__
+    cls.__init__ = __init__
+    cls.__doc__ = GhostBaseMetaClass.ghost_doc
+
+InitGhostBase = GhostBaseMetaClass('InitGhostBase', (ERP5Base,), {})
+
+class PortalTypeMetaClass(GhostBaseMetaClass):
   """
   Meta class that is used by portal type classes
 
@@ -79,7 +94,7 @@ class PortalTypeMetaClass(ExtensionClass):
         PortalTypeMetaClass.subclass_register.setdefault(parent, []).append(cls)
 
     cls.__ghostbase__ = None
-    super(PortalTypeMetaClass, cls).__init__(name, bases, dictionary)
+    super(GhostBaseMetaClass, cls).__init__(name, bases, dictionary)
 
   @classmethod
   def getSubclassList(metacls, cls):
@@ -124,7 +139,9 @@ class PortalTypeMetaClass(ExtensionClass):
                         '__ghostbase__',
                         'portal_type'):
           delattr(cls, attr)
-      cls.__bases__ = cls.__ghostbase__
+      # generate a ghostbase that derives from all previous bases
+      ghostbase = GhostBaseMetaClass('GhostBase', cls.__bases__, {})
+      cls.__bases__ = (ghostbase,)
       cls.__ghostbase__ = None
       cls.resetAcquisitionAndSecurity()
 
@@ -193,4 +210,4 @@ class PortalTypeMetaClass(ExtensionClass):
       ERP5Base.aq_method_lock.release()
 
 def generateLazyPortalTypeClass(portal_type_name):
-  return PortalTypeMetaClass(portal_type_name, (GhostPortalType,), {})
+  return PortalTypeMetaClass(portal_type_name, (InitGhostBase,), {})
diff --git a/product/ERP5Type/tests/testDynamicClassGeneration.py b/product/ERP5Type/tests/testDynamicClassGeneration.py
index 6e6cb87566eb49ef9aa2ddabd76b11f04b9fbf9a..99a07c5de3afdd1f082786e6b292eb42c079e3f8 100644
--- a/product/ERP5Type/tests/testDynamicClassGeneration.py
+++ b/product/ERP5Type/tests/testDynamicClassGeneration.py
@@ -240,6 +240,51 @@ class TestPortalTypeClass(ERP5TypeTestCase):
     implemented_by = list(implementedBy(InterfaceTestType))
     self.failIf(IForTest in implemented_by)
 
+  def testClassHierarchyAfterReset(self):
+    """
+    Check that after a class reset, the class hierarchy is unchanged until
+    un-ghostification happens. This is very important for multithreaded
+    environments:
+      Thread A. reset dynamic classes
+      Thread B. in Folder code for instance: CMFBTreeFolder.method(self)
+
+    If a reset happens before the B) method call, and does not keep the
+    correct hierarchy (for instance Folder superclass is removed from
+    the mro()), a TypeError might be raised:
+      "method expected CMFBTreeFolder instance, got erp5.portal_type.xxx
+      instead"
+
+    This used to be broken because the ghost state was only what is called
+    lazy_class.InitGhostBase: a "simple" subclass of ERP5Type.Base
+    """
+    name = "testClassHierarchyAfterReset Module"
+    types_tool = self.portal.portal_types
+
+    ptype = types_tool.newContent(id=name, type_class="Folder")
+    transaction.commit()
+    module_class = types_tool.getPortalTypeClass(name)
+    module_class.loadClass()
+
+    # first manually reset and check that everything works
+    from Products.ERP5Type.Core.Folder import Folder
+    self.assertTrue(issubclass(module_class, Folder))
+    synchronizeDynamicModules(self.portal, force=True)
+    self.assertTrue(issubclass(module_class, Folder))
+
+    # then change the type value to something not descending from Folder
+    # and check behavior
+    ptype.setTypeClass('Address')
+
+    # while the class has not been reset is should still descend from Folder
+    self.assertTrue(issubclass(module_class, Folder))
+    # finish transaction and trigger workflow/DynamicModule reset
+    transaction.commit()
+    # while the class has not been unghosted it's still a Folder
+    self.assertTrue(issubclass(module_class, Folder))
+    # but it changes as soon as the class is loaded
+    module_class.loadClass()
+    self.assertFalse(issubclass(module_class, Folder))
+
 class TestZodbPropertySheet(ERP5TypeTestCase):
   """
   XXX: WORK IN PROGRESS