Hi,
today I read again source code for Trac's ComponentManager while
debugging an issue. In the process I found that the code is prone to
race-conditions:
def maybe_init(self, compmgr, init=init, cls=new_class):
if cls not in compmgr.components:
compmgr.components[cls] = self
if init:
try:
init(self)
except:
del compmgr.components[cls]
raise
…
So is is a small time window where the process-wide dict contains
instances which have not been initialized. That caused some pretty weird
errors for us.
Obviously the correct solution is to add a lock before accessing the
compmgr.components.
However there is also a version which does not need any locks:
def maybe_init(self, compmgr, init=init, cls=new_class):
if cls not in compmgr.components:
if init:
init(self)
compmgr.components[cls] = self
…
I think the above version should work just as well as the current one
while preventing half-initialized instances in the cache, provided that
some basic assumptions are met:
- "compmgr.components[cls] = self" is atomic
- calling a constructor twice in the worst case is not a problem
- two components do not instantiate each others within their __init__
methods (currently the other gets a half-initialized version, the
latter version will cause an endless loop as two normal Python
objects would)
Comments?
fs
--
You received this message because you are subscribed to the Google Groups "Trac
Development" group.
To post to this group, send email to trac-...@googlegroups.com.
To unsubscribe from this group, send email to
trac-dev+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/trac-dev?hl=en.