Skip to content

Commit a6e1c1f

Browse files
ejona86JoeCqupt
andauthored
stub: trailersFromThrowable() metadata should be copied (#11979) (#12008)
If the same exception is passed to multiple RPCs, then the results will race, which this fix addresses. Fixes #11973 Co-authored-by: jiangyuan <[email protected]>
1 parent 8681786 commit a6e1c1f

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

stub/src/main/java/io/grpc/stub/ServerCalls.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,10 @@ public void onNext(RespT response) {
382382

383383
@Override
384384
public void onError(Throwable t) {
385-
Metadata metadata = Status.trailersFromThrowable(t);
386-
if (metadata == null) {
387-
metadata = new Metadata();
385+
Metadata metadata = new Metadata();
386+
Metadata trailers = Status.trailersFromThrowable(t);
387+
if (trailers != null) {
388+
metadata.merge(trailers);
388389
}
389390
call.close(Status.fromThrowable(t), metadata);
390391
aborted = true;

stub/src/test/java/io/grpc/stub/ServerCallsTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,35 @@ public void invoke(Integer req, StreamObserver<Integer> responseObserver) {
555555
listener.onHalfClose();
556556
}
557557

558+
@Test
559+
public void clientSendsOne_serverOnErrorWithTrailers_serverStreaming() {
560+
Metadata trailers = new Metadata();
561+
Metadata.Key<String> key = Metadata.Key.of("trailers-test-key1",
562+
Metadata.ASCII_STRING_MARSHALLER);
563+
trailers.put(key, "trailers-test-value1");
564+
565+
ServerCallRecorder serverCall = new ServerCallRecorder(SERVER_STREAMING_METHOD);
566+
ServerCallHandler<Integer, Integer> callHandler = ServerCalls.asyncServerStreamingCall(
567+
new ServerCalls.ServerStreamingMethod<Integer, Integer>() {
568+
@Override
569+
public void invoke(Integer req, StreamObserver<Integer> responseObserver) {
570+
responseObserver.onError(
571+
Status.fromCode(Status.Code.INTERNAL)
572+
.asRuntimeException(trailers)
573+
);
574+
}
575+
});
576+
ServerCall.Listener<Integer> listener = callHandler.startCall(serverCall, new Metadata());
577+
serverCall.isReady = true;
578+
serverCall.isCancelled = false;
579+
listener.onReady();
580+
listener.onMessage(1);
581+
listener.onHalfClose();
582+
// verify trailers key is set
583+
assertTrue(serverCall.trailers.containsKey(key));
584+
assertTrue(serverCall.status.equals(Status.INTERNAL));
585+
}
586+
558587
@Test
559588
public void inprocessTransportManualFlow() throws Exception {
560589
final Semaphore semaphore = new Semaphore(1);
@@ -652,6 +681,7 @@ private static class ServerCallRecorder extends ServerCall<Integer, Integer> {
652681
private boolean isCancelled;
653682
private boolean isReady;
654683
private int onReadyThreshold;
684+
private Metadata trailers;
655685

656686
public ServerCallRecorder(MethodDescriptor<Integer, Integer> methodDescriptor) {
657687
this.methodDescriptor = methodDescriptor;
@@ -674,6 +704,7 @@ public void sendMessage(Integer message) {
674704
@Override
675705
public void close(Status status, Metadata trailers) {
676706
this.status = status;
707+
this.trailers = trailers;
677708
}
678709

679710
@Override

0 commit comments

Comments
 (0)