mirror of https://github.com/grpc/grpc-java.git
stub: trailersFromThrowable() metadata should be copied (#11979)
If the same exception is passed to multiple RPCs, then the results will race. Fixes #11973
This commit is contained in:
parent
aae52de3b8
commit
54d37839a3
|
@ -382,9 +382,10 @@ public final class ServerCalls {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
Metadata metadata = Status.trailersFromThrowable(t);
|
Metadata metadata = new Metadata();
|
||||||
if (metadata == null) {
|
Metadata trailers = Status.trailersFromThrowable(t);
|
||||||
metadata = new Metadata();
|
if (trailers != null) {
|
||||||
|
metadata.merge(trailers);
|
||||||
}
|
}
|
||||||
call.close(Status.fromThrowable(t), metadata);
|
call.close(Status.fromThrowable(t), metadata);
|
||||||
aborted = true;
|
aborted = true;
|
||||||
|
|
|
@ -555,6 +555,35 @@ public class ServerCallsTest {
|
||||||
listener.onHalfClose();
|
listener.onHalfClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clientSendsOne_serverOnErrorWithTrailers_serverStreaming() {
|
||||||
|
Metadata trailers = new Metadata();
|
||||||
|
Metadata.Key<String> key = Metadata.Key.of("trailers-test-key1",
|
||||||
|
Metadata.ASCII_STRING_MARSHALLER);
|
||||||
|
trailers.put(key, "trailers-test-value1");
|
||||||
|
|
||||||
|
ServerCallRecorder serverCall = new ServerCallRecorder(SERVER_STREAMING_METHOD);
|
||||||
|
ServerCallHandler<Integer, Integer> callHandler = ServerCalls.asyncServerStreamingCall(
|
||||||
|
new ServerCalls.ServerStreamingMethod<Integer, Integer>() {
|
||||||
|
@Override
|
||||||
|
public void invoke(Integer req, StreamObserver<Integer> responseObserver) {
|
||||||
|
responseObserver.onError(
|
||||||
|
Status.fromCode(Status.Code.INTERNAL)
|
||||||
|
.asRuntimeException(trailers)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ServerCall.Listener<Integer> listener = callHandler.startCall(serverCall, new Metadata());
|
||||||
|
serverCall.isReady = true;
|
||||||
|
serverCall.isCancelled = false;
|
||||||
|
listener.onReady();
|
||||||
|
listener.onMessage(1);
|
||||||
|
listener.onHalfClose();
|
||||||
|
// verify trailers key is set
|
||||||
|
assertTrue(serverCall.trailers.containsKey(key));
|
||||||
|
assertTrue(serverCall.status.equals(Status.INTERNAL));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inprocessTransportManualFlow() throws Exception {
|
public void inprocessTransportManualFlow() throws Exception {
|
||||||
final Semaphore semaphore = new Semaphore(1);
|
final Semaphore semaphore = new Semaphore(1);
|
||||||
|
@ -652,6 +681,7 @@ public class ServerCallsTest {
|
||||||
private boolean isCancelled;
|
private boolean isCancelled;
|
||||||
private boolean isReady;
|
private boolean isReady;
|
||||||
private int onReadyThreshold;
|
private int onReadyThreshold;
|
||||||
|
private Metadata trailers;
|
||||||
|
|
||||||
public ServerCallRecorder(MethodDescriptor<Integer, Integer> methodDescriptor) {
|
public ServerCallRecorder(MethodDescriptor<Integer, Integer> methodDescriptor) {
|
||||||
this.methodDescriptor = methodDescriptor;
|
this.methodDescriptor = methodDescriptor;
|
||||||
|
@ -674,6 +704,7 @@ public class ServerCallsTest {
|
||||||
@Override
|
@Override
|
||||||
public void close(Status status, Metadata trailers) {
|
public void close(Status status, Metadata trailers) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
this.trailers = trailers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue