• Arnaud Fontaine's avatar
    ZODB Components: Fix deadlock between import lock and aq_method_lock. · 11456c69
    Arnaud Fontaine authored
    This only happens when using ZEO (see source code comments).
    
    Steps to reproduce:
      1. Edit a ZODB Component in one tab.
      2. At the same time, run Unit Tests in another tab.
    
    Backtrace:
    
      # ThreadID: 140153540167424
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZServer/PubCore/ZServerPublisher.py", line 31, in __init__
        response=b)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 455, in publish_module
        environ, debug, request, response)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 249, in publish_module_standard
        response = publish(request, module_name, after_list, debug=debug)
      File: "parts/erp5/Products/Localizer/patches.py", line 84, in new_publish
        x = zope_publish(request, module_name, after_list, debug)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 138, in publish
        request, bind=1)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/mapply.py", line 44, in mapply
        f, count = zope.publisher.publish.unwrapMethod(object)
      File: "eggs/zope.publisher-3.12.6-py2.7.egg/zope/publisher/publish.py", line 46, in unwrapMethod
        elif getattr(unwrapped, 'func_code', None) is not None:
      File: "eggs/Products.ExternalMethod-2.13.0-py2.7.egg/Products/ExternalMethod/ExternalMethod.py", line 106, in <lambda>
        func_code = ComputedAttribute(lambda self: self.getFuncCode())
      File: "eggs/Products.ExternalMethod-2.13.0-py2.7.egg/Products/ExternalMethod/ExternalMethod.py", line 190, in getFuncCode
        self._v_f = self.getFunction()
      File: "parts/erp5/Products/ERP5Type/patches/ExternalMethod.py", line 29, in getFunction
        level=0)
      File: "parts/erp5/Products/ERP5Type/dynamic/component_package.py", line 407, in load_module
        with aq_method_lock:
      File: "parts/python2.7/lib/python2.7/threading.py", line 174, in acquire
        rc = self.__block.acquire(blocking)
    
      => 1. Acquire Import lock in getFunction() (ZODB Component import)
         2. Try to acquire aq_method_lock
    
      # ThreadID: 140153468495616
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZServer/PubCore/ZServerPublisher.py", line 31, in __init__
        response=b)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 455, in publish_module
        environ, debug, request, response)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 249, in publish_module_standard
        response = publish(request, module_name, after_list, debug=debug)
      File: "parts/erp5/Products/Localizer/patches.py", line 84, in new_publish
        x = zope_publish(request, module_name, after_list, debug)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 138, in publish
        request, bind=1)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/mapply.py", line 77, in mapply
        if debug is not None: return debug(object,args,context)
      File: "eggs/Zope2-2.13.22-py2.7.egg/ZPublisher/Publish.py", line 48, in call_object
        result=apply(object,args) # Type s<cr> to step into published object.
      File: "parts/erp5/Products/TimerService/TimerService.py", line 90, in process_timer
        subscriptions.append(self.unrestrictedTraverse(path))
      File: "eggs/Zope2-2.13.22-py2.7.egg/OFS/Traversable.py", line 249, in unrestrictedTraverse
        if getattr(aq_base(obj), name, _marker) is not _marker:
      File: "parts/erp5/Products/ERP5Type/dynamic/lazy_class.py", line 107, in __getattribute__
        self.__class__.loadClass()
      File: "parts/erp5/Products/ERP5Type/dynamic/lazy_class.py", line 326, in loadClass
        class_definition = generatePortalTypeClass(site, portal_type)
      File: "parts/erp5/Products/ERP5Type/dynamic/portal_type_class.py", line 143, in generatePortalTypeClass
        type_class = portal_type.getTypeClass()
      File: "eggs/ZODB3-3.10.5+slapospatched001-py2.7-linux-x86_64.egg/ZODB/Connection.py", line 860, in setstate
        self._setstate(obj)
      File: "eggs/ZODB3-3.10.5+slapospatched001-py2.7-linux-x86_64.egg/ZODB/Connection.py", line 914, in _setstate
        self._reader.setGhostState(obj, p)
      File: "eggs/ZODB3-3.10.5+slapospatched001-py2.7-linux-x86_64.egg/ZODB/serialize.py", line 612, in setGhostState
        state = self.getState(pickle)
      File: "eggs/ZODB3-3.10.5+slapospatched001-py2.7-linux-x86_64.egg/ZODB/serialize.py", line 604, in getState
        unpickler.load() # skip the class metadata
      File: "eggs/ZODB3-3.10.5+slapospatched001-py2.7-linux-x86_64.egg/ZODB/serialize.py", line 474, in find_global
        return factory(conn, modulename, name)
      File: "eggs/Zope2-2.13.22-py2.7.egg/Zope2/App/ClassFactory.py", line 21, in ClassFactory
        m=__import__(module, _globals, _globals, _silly)
    
      => 1. Acquire aq_method_lock (generatePortalTypeClass())
         2. Try to import module and acquire Import lock
    11456c69
component_package.py 17.7 KB