New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 895400 link

Starred by 1 user

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Chrome
Pri: 2
Type: Task



Sign in to add a comment

Handle unimplemented gRPC requests

Project Member Reported by emaxx@chromium.org, Oct 15

Issue description

(This bug refers to the Chrome OS diagnostics project.)

When a gRPC client attempts to call a method that is not handled by the gRPC server, it currently hangs and returns only after the per-request deadline expires (which is 30 sec or so).
It'd be better if the client's request immediately returned with an error in such case.

And, as a related question, we need to investigate what happens when the client calls a method which simply didn't exist at the server's proto RPC definitions.
(Presumably, it boils down to the same case as described in the first paragraph, but we need to double-check that.)
 
Description: Show this description
Small correction: As per my manual test, looks like the client call actually hangs forever: I don't see the request completed even after several minutes.
Cc: lamzin@chromium.org
This seems to be the case becuase grpc's RegisterService which we call (
https://grpc.io/grpc/cpp/classgrpc_1_1_server_builder.html#a0b06b5828b892feeb6541c8eeae2d542 ) actually iterates all methods in the service and already registers them.

There doesn't seem to be a good way to avoid this behavior without a lot of complexity.

If the service definition at compile time didn't have a method, it _will_ answer a grpc error with the value UNIMPLEMENTED. I'll confirm this with a test case.

Assuming this is the case, is it OK to rely on the server calling RegisterHandler for all functions that are in the service definition at compile time?
I guess we would do this inside DPSL for all defined methods anyway, so it is not forgotten in diagnostics_processor.

Or do you think there's enough value to investigate additional safeguards (such as attempting to find out if there are methods that were not registered somehow and CHECK-failing then)?
Thanks for investigating.

So does the case "client is run against an older version of server which didn't have the new method" work differently, without hanging?
If so, it should be OK to leave it as is.
I wanted to write a test case for this, but it's hard to reproduce this case exactly (of the same service having one method less) because grpc uses the names from the proto descriptor (and I can't customize these).

However, at grpc level, it seems that a "service name" doesn't exist as a concept, resolution happens on method names instead.

For example, in the tests, the following is generated:
static const char* ExampleService_method_names[] = {
  "/diagnostics.test_rpcs.ExampleService/EmptyRpc",
  "/diagnostics.test_rpcs.ExampleService/EchoIntRpc",
  "/diagnostics.test_rpcs.ExampleService/AnotherEchoIntRpc",
};

when a call arrives, the matching is performed by comparing the call's "path" against the registered method (rm)'s method name - see https://github.com/grpc/grpc/blob/04c34590c6cdda071533b07dee987625f9f7aca7/src/core/lib/surface/server.cc#L621 .

This means that the situations
- Server exposes Service S without method M, Client tries to call method M of Service S
- Server does not expose Service S at all, Client triest to call method M of Service S
should be equivalent.

For the latter situation, there's https://github.com/grpc/grpc/blob/618a3f561d4a93f263cca23abad086ed8f4d5e86/test/cpp/end2end/end2end_test.cc#L1165

So we should be fine here.
Labels: Sarien
Labels: Type-Task

Sign in to add a comment