mirror of https://github.com/grpc/grpc-java.git
core: Don't mark calls as cancelled if they are successfully completed. (#8408)
The semantics around cancel vary slightly between ServerCall and CancellableContext - the context should always be cancelled regardless of the outcome of the call while the ServerCall should only be cancelled on a non-OK status. This fixes a bug where the ServerCall was always marked cancelled regardless of call status. Fixes #5882
This commit is contained in:
parent
c54fcba2ee
commit
e45aab085c
|
|
@ -279,7 +279,11 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
|
||||||
new Context.CancellationListener() {
|
new Context.CancellationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void cancelled(Context context) {
|
public void cancelled(Context context) {
|
||||||
ServerStreamListenerImpl.this.call.cancelled = true;
|
// If the context has a cancellation cause then something exceptional happened
|
||||||
|
// and we should also mark the call as cancelled.
|
||||||
|
if (context.cancellationCause() != null) {
|
||||||
|
ServerStreamListenerImpl.this.call.cancelled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MoreExecutors.directExecutor());
|
MoreExecutors.directExecutor());
|
||||||
|
|
@ -355,6 +359,8 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
|
||||||
} finally {
|
} finally {
|
||||||
// Cancel context after delivering RPC closure notification to allow the application to
|
// Cancel context after delivering RPC closure notification to allow the application to
|
||||||
// clean up and update any state based on whether onComplete or onCancel was called.
|
// clean up and update any state based on whether onComplete or onCancel was called.
|
||||||
|
// Note that in failure situations JumpToApplicationThreadServerStreamListener has already
|
||||||
|
// closed the context. In these situations this cancel() call will be a no-op.
|
||||||
context.cancel(null);
|
context.cancel(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package io.grpc.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Charsets.UTF_8;
|
import static com.google.common.base.Charsets.UTF_8;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
@ -378,6 +379,9 @@ public class ServerCallImplTest {
|
||||||
verify(callListener).onComplete();
|
verify(callListener).onComplete();
|
||||||
assertTrue(context.isCancelled());
|
assertTrue(context.isCancelled());
|
||||||
assertNull(context.cancellationCause());
|
assertNull(context.cancellationCause());
|
||||||
|
// The call considers cancellation to be an exceptional situation so it should
|
||||||
|
// not be cancelled with an OK status.
|
||||||
|
assertFalse(call.isCancelled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -1196,7 +1196,9 @@ public class ServerImplTest {
|
||||||
context, contextCancelled, null);
|
context, contextCancelled, null);
|
||||||
|
|
||||||
// For close status OK:
|
// For close status OK:
|
||||||
// isCancelled is expected to be true after all pending work is done
|
// The context isCancelled is expected to be true after all pending work is done,
|
||||||
|
// but for the call it should be false as it gets set cancelled only if the call
|
||||||
|
// fails with a non-OK status.
|
||||||
assertFalse(callReference.get().isCancelled());
|
assertFalse(callReference.get().isCancelled());
|
||||||
assertFalse(context.get().isCancelled());
|
assertFalse(context.get().isCancelled());
|
||||||
streamListener.closed(Status.OK);
|
streamListener.closed(Status.OK);
|
||||||
|
|
@ -1204,7 +1206,7 @@ public class ServerImplTest {
|
||||||
assertFalse(context.get().isCancelled());
|
assertFalse(context.get().isCancelled());
|
||||||
|
|
||||||
assertEquals(1, executor.runDueTasks());
|
assertEquals(1, executor.runDueTasks());
|
||||||
assertTrue(callReference.get().isCancelled());
|
assertFalse(callReference.get().isCancelled());
|
||||||
assertTrue(context.get().isCancelled());
|
assertTrue(context.get().isCancelled());
|
||||||
assertTrue(contextCancelled.get());
|
assertTrue(contextCancelled.get());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue