diff options
author | Thomas Van Lenten <thomasvl@google.com> | 2017-03-02 14:50:10 -0500 |
---|---|---|
committer | Thomas Van Lenten <thomasvl@google.com> | 2017-03-02 16:34:11 -0500 |
commit | 2d1c5e26cb291193ac4d1f4a5179d8f6e1906229 (patch) | |
tree | 1486c2e0c6ffa3e5121f00096b27b52450f5a395 /objectivec/GPBMessage.m | |
parent | a7e3b0ab016312f7427426d2cb88b0ab77210b79 (diff) | |
download | protobuf-2d1c5e26cb291193ac4d1f4a5179d8f6e1906229.tar.gz protobuf-2d1c5e26cb291193ac4d1f4a5179d8f6e1906229.tar.bz2 protobuf-2d1c5e26cb291193ac4d1f4a5179d8f6e1906229.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]; |