aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/objective-c/ProtoRPC
diff options
context:
space:
mode:
authorGravatar Muxi Yan <mxyan@google.com>2018-10-22 18:25:16 -0700
committerGravatar Muxi Yan <mxyan@google.com>2018-10-22 18:25:16 -0700
commite13c8678264d85353bb2ce49ae829c03f6c9493f (patch)
tree8b09b21775c64fc4888fdda395e8792d43a236e6 /src/objective-c/ProtoRPC
parent3566540f16451ea87aff980b5de13c41a8debeb6 (diff)
Do not issue more message when the call is canceled
Diffstat (limited to 'src/objective-c/ProtoRPC')
-rw-r--r--src/objective-c/ProtoRPC/ProtoRPC.m43
1 files changed, 33 insertions, 10 deletions
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m
index 28c037e609..a6c88488fc 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.m
+++ b/src/objective-c/ProtoRPC/ProtoRPC.m
@@ -66,6 +66,11 @@
GRPCCall2 *_call;
dispatch_queue_t _dispatchQueue;
+ /**
+ * Flags that the call has been canceled. When this is true, pending initial metadata and message
+ * should not be issued to \a _handler. This ivar must be accessed with lock to self.
+ */
+ BOOL _canceled;
}
- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions
@@ -95,6 +100,7 @@
_dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);
}
dispatch_set_target_queue(handler.dispatchQueue, _dispatchQueue);
+ _canceled = NO;
[self start];
}
@@ -110,12 +116,15 @@
- (void)cancel {
dispatch_async(_dispatchQueue, ^{
- if (_call) {
- [_call cancel];
- _call = nil;
+ if (self->_call) {
+ [self->_call cancel];
+ self->_call = nil;
}
- if (_handler) {
- id<GRPCProtoResponseHandler> handler = _handler;
+ if (self->_handler) {
+ @synchronized(self) {
+ self->_canceled = YES;
+ }
+ id<GRPCProtoResponseHandler> handler = self->_handler;
if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) {
dispatch_async(handler.dispatchQueue, ^{
[handler closedWithTrailingMetadata:nil
@@ -127,7 +136,7 @@
}]];
});
}
- _handler = nil;
+ self->_handler = nil;
}
});
}
@@ -155,10 +164,17 @@
- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata {
if (_handler && initialMetadata != nil) {
- id<GRPCProtoResponseHandler> handler = _handler;
+ __block id<GRPCResponseHandler> handler = _handler;
if ([handler respondsToSelector:@selector(initialMetadata:)]) {
dispatch_async(handler.dispatchQueue, ^{
- [handler receivedInitialMetadata:initialMetadata];
+ // Do not issue initial metadata if the call is already canceled.
+ __block BOOL canceled = NO;
+ @synchronized(self) {
+ canceled = self->_canceled;
+ }
+ if (!canceled) {
+ [handler receivedInitialMetadata:initialMetadata];
+ }
});
}
}
@@ -166,13 +182,20 @@
- (void)receivedRawMessage:(NSData *_Nullable)message {
if (_handler && message != nil) {
- id<GRPCProtoResponseHandler> handler = _handler;
+ __block id<GRPCProtoResponseHandler> handler = _handler;
NSError *error = nil;
GPBMessage *parsed = [_responseClass parseFromData:message error:&error];
if (parsed) {
if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) {
dispatch_async(handler.dispatchQueue, ^{
- [handler receivedProtoMessage:parsed];
+ // Do not issue message if the call is already canceled.
+ __block BOOL canceled = NO;
+ @synchronized(self) {
+ canceled = self->_canceled;
+ }
+ if (!canceled) {
+ [handler receivedProtoMessage:parsed];
+ }
});
}
} else {