diff options
author | Muxi Yan <mxyan@google.com> | 2018-10-22 18:25:16 -0700 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2018-10-22 18:25:16 -0700 |
commit | e13c8678264d85353bb2ce49ae829c03f6c9493f (patch) | |
tree | 8b09b21775c64fc4888fdda395e8792d43a236e6 /src/objective-c/ProtoRPC/ProtoRPC.m | |
parent | 3566540f16451ea87aff980b5de13c41a8debeb6 (diff) |
Do not issue more message when the call is canceled
Diffstat (limited to 'src/objective-c/ProtoRPC/ProtoRPC.m')
-rw-r--r-- | src/objective-c/ProtoRPC/ProtoRPC.m | 43 |
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 { |