Closed
Description
Using v1.8.0.
The following client/server leaves the bidi RPC call open, holding onto resources and ultimately going OOM if enough calls are made:
// proto
message Request {}
message Response {}
service TestService {
rpc Ping(stream Request) returns (stream Response);
}
/////////////////////////////
// server impl
private static class ServerServiceImpl extends TestServiceGrpc.TestServiceImplBase {
@Override
public StreamObserver<TestRpc.Request> ping(StreamObserver<example.TestRpc.Response> responseObserver) {
return new StreamObserver<TestRpc.Request>() {
@Override
public void onNext(TestRpc.Request request) {
responseObserver.onNext(TestRpc.Response.newBuilder().build());
responseObserver.onCompleted();
}
@Override public void onError(Throwable throwable) {}
@Override public void onCompleted() {}
};
}
}
/////////////////////////////
// client impl
private void oneCall(Channel chan) {
ClientCall<TestRpc.Request, TestRpc.Response> call =
chan.newCall(TestServiceGrpc.getPingMethod(), CallOptions.DEFAULT);
call.start(new ClientCall.Listener<TestRpc.Response>(), new Metadata());
call.sendMessage(TestRpc.Request.newBuilder().build());
call.request(1);
}
for (int i = 0; i < 1000; ++i) {
oneCall(channel);
}
// If I attach a debugger to the client here, I can see 1000 instances of DefaultStream and 1000 instances of a bunch of other grpc/netty bits, even after > 5 minutes and repeated attempts at GC.
Thread.sleep(9999999);
Replacing the client's ClientCall.Listener
with one that calls .halfClose()
upon completion works around the issue.