diff options
author | Thomas Van Lenten <thomasvl@google.com> | 2017-03-02 14:50:10 -0500 |
---|---|---|
committer | Bo Yang <paulyang1211@gmail.com> | 2017-03-03 10:13:22 -0800 |
commit | 4020fe427cf71f616e00bc39f8155b9bed8fd47c (patch) | |
tree | 8cd7f0143903b8f288a42c1a54856d3649b1431b /objectivec/GPBMessage.m | |
parent | fa925b98937bafee6b5d7244cce5c1ad39bf9d36 (diff) | |
download | protobuf-4020fe427cf71f616e00bc39f8155b9bed8fd47c.tar.gz protobuf-4020fe427cf71f616e00bc39f8155b9bed8fd47c.tar.bz2 protobuf-4020fe427cf71f616e00bc39f8155b9bed8fd47c.zip |
Handing threading race resolving methods.
- Don't prune the extension registry as that can lead to failures when two
threads are racing.
- If adding the method fails, check and see if it already is bound to decide
the return result. Deals with threading races binding the methods.
Diffstat (limited to 'objectivec/GPBMessage.m')
-rw-r--r-- | objectivec/GPBMessage.m | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 9660f1ed..58a10fdb 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -3152,8 +3152,17 @@ static void ResolveIvarSet(GPBFieldDescriptor *field, if (result.impToAdd) { const char *encoding = GPBMessageEncodingForSelector(result.encodingSelector, YES); - BOOL methodAdded = class_addMethod(descriptor.messageClass, sel, - result.impToAdd, encoding); + Class msgClass = descriptor.messageClass; + BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding); + // class_addMethod() is documented as also failing if the method was already + // added; so we check if the method is already there and return success so + // the method dispatch will still happen. Why would it already be added? + // Two threads could cause the same method to be bound at the same time, + // but only one will actually bind it; the other still needs to return true + // so things will dispatch. + if (!methodAdded) { + methodAdded = GPBClassHasSel(msgClass, sel); + } return methodAdded; } return [super resolveInstanceMethod:sel]; |