aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Muxi Yan <mxyan@google.com>2019-01-07 16:51:23 -0800
committerGravatar Muxi Yan <mxyan@google.com>2019-01-07 16:51:23 -0800
commitcf303c3ee7d4b4364650ca6fdecbaafdca117497 (patch)
tree0682b29e475d0adf9084978b9f485dadf98cf8f7 /src
parentd7650a841b8acac747b5a8d12502a46ec0e4a54c (diff)
Deadlock fix for GRPCCall
Diffstat (limited to 'src')
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m47
1 files changed, 18 insertions, 29 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index c18dfae635..714c7dbbc2 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -539,26 +539,24 @@ const char *kCFStreamVarName = "grpc_cfstream";
#pragma mark Finish
+// This function should support being called within a @synchronized(self) block in another function
+// Should not manipulate _requestWriter for deadlock prevention.
- (void)finishWithError:(NSError *)errorOrNil {
- GRXConcurrentWriteable *copiedResponseWriteable = nil;
-
@synchronized(self) {
if (_state == GRXWriterStateFinished) {
return;
}
_state = GRXWriterStateFinished;
- copiedResponseWriteable = _responseWriteable;
+
+ if (errorOrNil) {
+ [_responseWriteable cancelWithError:errorOrNil];
+ } else {
+ [_responseWriteable enqueueSuccessfulCompletion];
+ }
// If the call isn't retained anywhere else, it can be deallocated now.
_retainSelf = nil;
}
-
- if (errorOrNil) {
- [copiedResponseWriteable cancelWithError:errorOrNil];
- } else {
- [copiedResponseWriteable enqueueSuccessfulCompletion];
- }
- _requestWriter.state = GRXWriterStateFinished;
}
- (void)cancel {
@@ -572,19 +570,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]];
[_wrappedCall cancel];
}
-}
-
-- (void)maybeFinishWithError:(NSError *)errorOrNil {
- BOOL toFinish = NO;
- @synchronized(self) {
- if (_finished == NO) {
- _finished = YES;
- toFinish = YES;
- }
- }
- if (toFinish == YES) {
- [self finishWithError:errorOrNil];
- }
+ _requestWriter.state = GRXWriterStateFinished;
}
- (void)dealloc {
@@ -647,6 +633,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
}]];
[strongSelf->_wrappedCall cancel];
}
+ strongSelf->_requestWriter.state = GRXWriterStateFinished;
} else {
@synchronized(strongSelf) {
[strongSelf->_responseWriteable enqueueValue:data
@@ -818,6 +805,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
}
[strongSelf finishWithError:error];
+ strongSelf->_requestWriter.state = GRXWriterStateFinished;
}
}];
}
@@ -841,12 +829,12 @@ const char *kCFStreamVarName = "grpc_cfstream";
callOptions:_callOptions];
if (_wrappedCall == nil) {
- [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
- code:GRPCErrorCodeUnavailable
- userInfo:@{
- NSLocalizedDescriptionKey :
- @"Failed to create call or channel."
- }]];
+ [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+ code:GRPCErrorCodeUnavailable
+ userInfo:@{
+ NSLocalizedDescriptionKey :
+ @"Failed to create call or channel."
+ }]];
return;
}
@@ -971,6 +959,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
NSLocalizedDescriptionKey : @"Connectivity lost."
}]];
}
+ strongSelf->_requestWriter.state = GRXWriterStateFinished;
}
}