2013-10-11 10:51:38 |
Guewen Baconnier @ Camptocamp |
description |
Hi,
I just get caught by this bug, which is very hard to reproduce.
It happens only when:
- you have a thread which starts when a module is loaded
- the thread calls openerp.pooler.get_pool()
- OpenERP is started from an external script, like "behave" or with "oe" when running the python tests (does not seems to happen when started from openerp-server)
It gives errors as this example:
File ".../server/openerp/service/web_services.py", line 433, in dispatch
return fn(*params)
File ".../server/openerp/service/web_services.py", line 438, in exp_login
res = security.login(db, login, password)
File ".../server/openerp/service/security.py", line 31, in login
return user_obj.login(db, login, password)
AttributeError: 'NoneType' object has no attribute 'login'
Cause:
RegistryManager.get() on:
http://bazaar.launchpad.net/~openerp/openobject-server/7.0/view/5096/openerp/modules/registry.py#L185
It must be protected by cls.registries_lock because it may return the registry from cls.registries or create a new one.
What happens when there is no registry and 2 threads calls RegistryManager.get() at the same time:
- they both have a KeyError
- they both execute RegistryManager.new(). This one is protected by the RLock but that's already too late
- the first threads create a new Registry. RegistryManager.get() returns this Registry
- then the second thread create a new Registry and replace the first one in cls.registries. RegistryManager.get() returns this Registry
If RegistryManager.get() have been surrounded by a RLock, the second thread would just have waited and would not have created a new Registry.
The branch is coming. |
Hi,
I just get caught by this bug, which is very hard to reproduce.
It happens only when:
- you have more than 1 thread which starts when a module is loaded
- a child thread calls openerp.pooler.get_pool()
- OpenERP is started from an external script, like "behave" or "oe" when running the python tests (does not seems to happen when started from openerp-server)
It gives errors as this example:
File ".../server/openerp/service/web_services.py", line 433, in dispatch
return fn(*params)
File ".../server/openerp/service/web_services.py", line 438, in exp_login
res = security.login(db, login, password)
File ".../server/openerp/service/security.py", line 31, in login
return user_obj.login(db, login, password)
AttributeError: 'NoneType' object has no attribute 'login'
Cause:
RegistryManager.get() on:
http://bazaar.launchpad.net/~openerp/openobject-server/7.0/view/5096/openerp/modules/registry.py#L185
It must be protected by cls.registries_lock because it may return the registry from cls.registries or create a new one.
What happens when there is no registry and 2 threads calls RegistryManager.get() at the same time:
1. they both have a KeyError
2. they both execute RegistryManager.new(). This one is protected by the RLock but that's already too late
3. the first thread create a new Registry. RegistryManager.get() returns this Registry
4. then the second thread create a new Registry and replace the first one in cls.registries. RegistryManager.get() returns this Registry
5. One of the registry (could not see which) has no models => self.pool.get() always returns None
If RegistryManager.get() had been surrounded by a RLock, the second thread would just have waited and would not have created a new Registry.
The branch is coming. |
|