-
-
Notifications
You must be signed in to change notification settings - Fork 58
Description
Describe the bug
ObjCClass maintains a cache of ObjC method/property references. This cache is populated on first use.
If you have multiple threads using the same Objective C class, there is a potential race condition. If the first thread tries to access a method or property, it will detect that the cache is empty, and attempt to populate it.
ObjCClass._load_methods()
involves an iteration over all methods in the class, and over all methods in the superclasses, adding methods to the method cache as they are discovered.
If thread 1 attempts to invoke a method, and discovers the method cache is empty, it will begin to load the method cache. However, this puts the method cache into a state where it no longer appears to be unpopulated; so if a second thread attempts to access a any method on the same class, it will discover an apparently populated cache, and use that cache to access the method. If the method hasn't been populated by the first thread, the second thread will get an AttributeError, even though the attribute is actually valid.
Steps to reproduce
Run the Toga GUI test case on macOS or iOS (currently in the macos-probe
branch). This problem manifests infrequently - maybe every ~50 executions.
Expected behavior
Attribute access should be reliable and idempotent.
Screenshots
No response
Environment
- Operating System: macOS, iOS
- Python version: All
- Software versions:
- Briefcase: 0.3.12+
- Toga: 0.3.12+
Logs
I haven't got an example to hand - but it always manifests as a vanilla AttributeError
on an attribute that should exist.
Additional context
Discovered while testing beeware/toga#1707.