Hello Felix,

On 10/18/2010 4:58 PM, Felix Schwarz wrote:

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:

Yup, it's a known issue, it just didn't get high enough on the priority list so far. Jun Omae reported issue #9418 some times ago, and I reported #8658 even earlier.


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
    …


So this is exactly the same solution as the one I proposed for #8658; I suppose this validates it ;-)

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?

I think we can adopt the simple solution for 0.12.2.

Jun came with an even better fix on #9418 (http://trac.edgewall.org/attachment/ticket/9418/9416-r9841-without-lock.diff) that we should probably apply on trunk. Now that you're familiar with the problem, you should perhaps also review and comment on that solution.

-- Christian

--
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.

Reply via email to