Repository navigation
Lazy properties are not threadsafe #11221
Description
Activity
Re: cached_property -- I am not sure when we're dropping support for Python 3.7 though.
As for
units, perhaps @mhvk can advise?Thanks for reporting! I think @embray is most relevant here since he wrote the code... But I'm obviously interested in getting the parser/lexer to work more reliably too!
Just for reference, the cached property implementation is at https://github.com/python/cpython/blob/49c150f1f16398a4e77e051244f27adc5ac7b47b/Lib/functools.py#L933-L980
A difference withlazypropertyis that it does not allow having a setter.I guess there is also a more general question to what extent we aim to be thread-safe, as I think so far we have not tried much (balance with readability and speed for unthreaded). Though certainly for widely used things such as
lazyproperty, we might as we well try to do it right, and similarly for the unit parsing/lexing. And I would love astropy to interact well with dask...Re: cached_property -- I am not sure when we're dropping support for Python 3.7 though.
Sorry, I was rambling a bit and didn't make a clear point. My point here is that
cached_propertyis proof that it's possible to make this thread-safe without sacrificing performance for the already-initialised case - although I haven't considered setters. Are setters a performance-critical path, or are they expected to be used just occasionally?I will make PRs for this and #11220.
- added a commit that references this issue
on Jan 8, 2021 I've made a PR. Unfortunately that turns out not to fix the specific Unit bug I mentioned, so I'll create a separate issue for that.
I guess there is also a more general question to what extent we aim to be thread-safe, as I think so far we have not tried much (balance with readability and speed for unthreaded).
The context of these thread safety bugs is that these are all issues that have arisen when trying to incorporate astropy into some code for the Square Kilometre Array.
@bmerry, thanks! I don't think there is much worry about performance for the setters. And, yes, helping to get SKA working is definitely a good reason!
- added 2 commits that reference this issue
on Feb 21, 2021 - added a commit that references this issue
on Feb 28, 2021 - added a commit that references this issue
on Mar 9, 2021
Description
The
@lazypropertydecorator and@classpropertydecorator withlazy=Truehave race conditions when accessing the cache, which can lead to sporadic errors when using astropy from multithreaded code e.g. dask. One such case is with the Unit parser.The Python 3.8
cached_property(mentioned in #9036) is thread-safe, and looking at the implementation it seems to use a double-checked locking pattern so the approach shouldn't hurt performance. Let me know if you'd like me to make a PR.Expected behavior
I expect to be able to parse unit strings safely from multi-threaded code.
Actual behavior
Running the script below sometimes leads to this exception (I run the script in a loop in the shell and it triggers within a second):
I'm not totally sure that this is the cause (or is the only cause), but
astropy.units.format.generic.Genericuses lazy class properties for the lexer and parser, and if several threads try to access the property at the same time, they could each try to build their own copy. I don't know about the lexer, but the comments at the top of astropy/extern/ply/yacc.py suggest that building parsers in parallel is a Bad Idea.Steps to Reproduce
Run this code in bash with
while ./astropy-constants-threading.py ; do :; doneuntil it errors.System Details