grpc-labview icon indicating copy to clipboard operation
grpc-labview copied to clipboard

Reusing ClientContext for multiple calls crashes LabVIEW

Open bkeryan opened this issue 2 years ago • 3 comments

Reusing a ClientContext for multiple unary calls crashes LabVIEW.

Top of call stack:

	labview_grpc_server.dll!abort() Line 77	C++
>	labview_grpc_server.dll!grpc::ClientContext::set_call(grpc_call * call, const std::shared_ptr<grpc::Channel> & channel) Line 117	C++
	labview_grpc_server.dll!grpc::Channel::CreateCallInternal(const grpc::internal::RpcMethod & method, grpc::ClientContext * context, grpc::CompletionQueue * cq, unsigned __int64 interceptor_pos) Line 152	C++
	labview_grpc_server.dll!grpc::Channel::CreateCall(const grpc::internal::RpcMethod & method, grpc::ClientContext * context, grpc::CompletionQueue * cq) Line 160	C++
	labview_grpc_server.dll!grpc::internal::BlockingUnaryCallImpl<grpc_labview::LVMessage,grpc_labview::LVMessage>::BlockingUnaryCallImpl<grpc_labview::LVMessage,grpc_labview::LVMessage>(grpc::ChannelInterface * channel, const grpc::internal::RpcMethod & method, grpc::ClientContext * context, const grpc_labview::LVMessage & request, grpc_labview::LVMessage * result) Line 70	C++
	labview_grpc_server.dll!grpc::internal::BlockingUnaryCall<grpc_labview::LVMessage,grpc_labview::LVMessage,grpc_labview::LVMessage,grpc_labview::LVMessage>(grpc::ChannelInterface * channel, const grpc::internal::RpcMethod & method, grpc::ClientContext * context, const grpc_labview::LVMessage & request, grpc_labview::LVMessage * result) Line 52	C++

This assertion is in the gRPC C Core, which documents that ClientContext instances should not be reused across RPCs.

I think it would be helpful for ClientUnaryCall, ClientBeginClientStreamingCall, etc. to check whether clientContext->gRPCClientContext.call() is null and return an error if it's not. That way, G developers don't have to rebuild labview_grpc_server.dll to figure out what's wrong with their code.

AB#2272018

bkeryan avatar Dec 16 '22 21:12 bkeryan

As of 1.0.1.1, this appears to have been fixed. Best I can tell, anyways.

Reusing it (on my machine, with local loopback) gets me a round trip time of 142 us. Opening a new one gets me a round trip time averaging 560 us. So it appears I'm shortcutting something by reusing it.

If reusing it is doing something wrong, I don't see any sign of a problem, other than going faster.

AndrewHeim avatar Dec 05 '23 23:12 AndrewHeim

The gRPC C Core's policy on reusing client contexts hasn't changed and is unlikely to change. The assertion is still present: https://github.com/grpc/grpc/blob/master/src/cpp/client/client_context.cc#L128

grpc_client.cc doesn't seem to have any code for resetting/reallocating the gRPC client context. Are assertions still enabled?

bkeryan avatar Dec 06 '23 15:12 bkeryan

I can't speak to whether assertions are enabled. But I can say that #320 and #193 acted up more often when I reused the grpc context.

That doesn't seem to make immediate sense to me, as the race condition behind those issues looks like it would be unaffected by reusing the context - it's about how quickly the call to the server returns. Or maybe it slowed things down enough that I ran fewer iterations in a few minutes of testing and reduced the likelihood I'd see the issue in a given amount of testing time? I can't say.

AndrewHeim avatar Dec 06 '23 22:12 AndrewHeim