aboutsummaryrefslogtreecommitdiff
path: root/objectivec/GPBMessage.m
diff options
context:
space:
mode:
authorThomas Van Lenten <thomasvl@google.com>2017-03-02 14:50:10 -0500
committerThomas Van Lenten <thomasvl@google.com>2017-03-02 16:34:11 -0500
commit2d1c5e26cb291193ac4d1f4a5179d8f6e1906229 (patch)
tree1486c2e0c6ffa3e5121f00096b27b52450f5a395 /objectivec/GPBMessage.m
parenta7e3b0ab016312f7427426d2cb88b0ab77210b79 (diff)
downloadprotobuf-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.m13
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];