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:
jiangyuan 2025-04-08 05:34:57 +08:00 committed by GitHub
parent aae52de3b8
commit 54d37839a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 3 deletions

View File

@ -382,9 +382,10 @@ public final class ServerCalls {
@Override
public void onError(Throwable t) {
Metadata metadata = Status.trailersFromThrowable(t);
if (metadata == null) {
metadata = new Metadata();
Metadata metadata = new Metadata();
Metadata trailers = Status.trailersFromThrowable(t);
if (trailers != null) {
metadata.merge(trailers);
}
call.close(Status.fromThrowable(t), metadata);
aborted = true;

View File

@ -555,6 +555,35 @@ public class ServerCallsTest {
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
public void inprocessTransportManualFlow() throws Exception {
final Semaphore semaphore = new Semaphore(1);
@ -652,6 +681,7 @@ public class ServerCallsTest {
private boolean isCancelled;
private boolean isReady;
private int onReadyThreshold;
private Metadata trailers;
public ServerCallRecorder(MethodDescriptor<Integer, Integer> methodDescriptor) {
this.methodDescriptor = methodDescriptor;
@ -674,6 +704,7 @@ public class ServerCallsTest {
@Override
public void close(Status status, Metadata trailers) {
this.status = status;
this.trailers = trailers;
}
@Override