Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve error returned by Send on server side after stream is reset #3575

Open
euroelessar opened this issue Apr 28, 2020 · 7 comments
Open

Comments

@euroelessar
Copy link

euroelessar commented Apr 28, 2020

Please see the FAQ in our main README.md, then answer the questions below before
submitting your issue.

What version of gRPC are you using?

1.29.0

What did you do?

Use SendAndClose or Send on server side for streaming requests. Client stream was reset by grpc stack right before that (e.g. by sending reset or by violating http/2 spec in some way).

What did you expect to see?

SendAndClose returns io.EOF or some error with non-Internal code to indicate about the error.

What did you see instead?

rpc error: code = Internal desc = transport: transport: the stream is done
or WriteHeader was already called

gRPC returns an error with Internal code, indicating API misuse, while application has no way to perform correctly in this case. Any checks (including ctx.Done()) would have been racy as stream is reset by grpc-go from another goroutine.

@menghanl
Copy link
Contributor

There's no SendClose. If you meant CloseSend, it's client side only, how do you use it on server side?

And can you provide more information of what client/server do in the failure? Like what methods are called, and in what order.

@euroelessar
Copy link
Author

Sorry, I've meant SendAndClose at server side.

Few examples:

  1. Stream-unary RPC at server side
    1.1. Server calls stream.Recv() until receiving io.EOF
    1.2. Client resets the stream by dying
    1.3. Server calls SendAndClose to send response back to client.
    1.4. SendAndClose returns the error in the issue
  2. Stream-stream RPC at server side
    2.1. Server sleeps some time after receiving the request
    2.2. Client resets the stream by dying
    2.3. Server calls Send to send first payload to client
    2.4. Send returns the error in the issue

@menghanl
Copy link
Contributor

It sounds right to me for send to return error when the underlying stream is broken. We can argue about the error message.

And what do you do about a sending error on the server side? The service handler should return something, but the error will never be sent to the client because the stream is already broken.

@euroelessar
Copy link
Author

It sounds right to me for send to return error when the underlying stream is broken. We can argue about the error message.

I agree that it's mainly about a content of the error (code/message).

Internal should be reserved for an actual invariant violations/API misuse. For example, it's perfectly fine to return Internal error on SendHeader if SendHeader/Send/etc were already invoked by caller as it is a protocol violation and is likely an indicator of a broken code.

Returning an error with the same Internal code on expected failure modes is not helpful as the only action item for an user it to just ignore this errors and never look at their status codes/content.

And what do you do about a sending error on the server side? The service handler should return something, but the error will never be sent to the client because the stream is already broken.

We usually check its code and aggregate all suspicious errors in a central storage. That's how this particular error did come to our attention.

@menghanl menghanl changed the title ErrIllegalHeaderWrite returned on reset streams by Send/SendClose improve error returned by Send on server side after stream is reset Apr 30, 2020
@dfawley
Copy link
Member

dfawley commented May 7, 2020

Maybe something like grpc.ErrConnectionBroken should be used for this kind of case. Regardless, the server side should not see RPC status errors at all, so Internal or any other code would be invalid here. RPC statuses should only be returned to clients for RPC operations.

@zouyee
Copy link
Contributor

zouyee commented Jun 9, 2020

/assign
/remove help

@dfawley
Copy link
Member

dfawley commented Jun 19, 2020

@zouyee thanks for the offer. What changes do you propose to make to fix this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants