Merge lp://staging/~gagern/bzr/bug396819-lazy_import-threadsafe into lp://staging/bzr
Status: | Merged |
---|---|
Merged at revision: | 6426 |
Proposed branch: | lp://staging/~gagern/bzr/bug396819-lazy_import-threadsafe |
Merge into: | lp://staging/bzr |
Diff against target: |
304 lines (+115/-82) 3 files modified
bzrlib/builtins.py (+11/-2) bzrlib/lazy_import.py (+67/-53) bzrlib/tests/test_lazy_import.py (+37/-27) |
To merge this branch: | bzr merge lp://staging/~gagern/bzr/bug396819-lazy_import-threadsafe |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Packman (community) | Needs Fixing | ||
Jelmer Vernooij (community) | Abstain | ||
Vincent Ladeuil | Needs Information | ||
John A Meinel | Pending | ||
Benji York | Pending | ||
Review via email: mp+73475@code.staging.launchpad.net |
Commit message
Make lazy imports (more) thread-safe
Description of the change
I know this still lacks a news entry, but apart from that, would you be willing to merge something along these lines to make lazy imports properly thread safe?
As I argued in bug #396819, I believe that you cannot have guaranteed tread-safe lazy imports without allowing the same replacer to resolve to the real object an arbitrary number of times. And you cannot avoid duplicate calls to the fatory (i.e. duplicate imports) unless you want to use locks.
The attached code avoids locks, as concurrent replacements should be rare and as duplicate imports should be harmless except for a slight cpu time penalty to detect it. It simplifies the replacer class by introducing a _resolve method which always returns the actual object.
As there are no longer any errors when the replace code is called repeatedly, we might miss the fact that the replacer object itself has been copied to some other name. To deal with this problem, the old error-raising behaviour will be restored for selftests, thus ensuring that the code is clean in that respect. Obviously, when the selftests reach the part where the thread safety of the replacer is tested, those checks have to be disabled again...
If you want any kind of beautification, name changes, or whatever, simply ask me or feel free to branch this yourself and apply changes as you see fit. I'm only proposing the general idea as a kind of proof of concept, and thus am most interested in your overall general opinion.
Thanks for working on this !
This looks promising and I won't mind polishing it as patch pilot
(or helping you) but before digging I'd like some feedback from
jam and benji which have been involved recently.
[feedback] Overall, the approach sounds good. I'm not sure I'm _replace( ) the only place where races can occur. If
reading this correctly but it seems you've now made
ScopeReplacer.
that's the case and we want to lock something, that should
probably be there.
[nit]
17 +
18 + disallow_proxying()
A bit naked ;) A comment explaining why it's done here (as early
as possible but no sooner) will be good.
[needsinfo]
218 - if event == 'line' and 'lazy_import.py' in filename: getline( filename, frame.f_lineno) endswith( 'lazy_import. py') and to_trace) :
219 - line = linecache.
220 - # ...and the line of code is the one we're looking for...
221 - if 'del self._factory' in line:
<...>
228 + if (filename.
229 + function_name == self.method_
This looks nice and less hackish, but I thought you were relying
on the code you're replacing here in lp:~gagern/bzr/bug-702914 ?
I wouldn't mind merging these tests instead (or their moral equivalent).