transport: Propagate status code on receiving RST_STREAM during message read - #8289
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #8289 +/- ##
==========================================
+ Coverage 82.14% 82.27% +0.13%
==========================================
Files 417 419 +2
Lines 41344 41992 +648
==========================================
+ Hits 33961 34550 +589
- Misses 5957 5982 +25
- Partials 1426 1460 +34
🚀 New features to boost your workflow:
|
b603bef to
78f39c7
Compare
78f39c7 to
af8bb07
Compare
af8bb07 to
6a24978
Compare
| } | ||
| t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode), nil, false) | ||
| st := status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode) | ||
| t.closeStream(s, st.Err(), false, http2.ErrCodeNo, st, nil, false) |
There was a problem hiding this comment.
@dfawley I've changed the code to use a status error for unblocking the reader. This bypasses the conversion to io.ErrUnexpectedEOF and doesn't require reading the status in csAttempt.recvMsg().
There was a problem hiding this comment.
Where is that conversion happening?
| } | ||
| t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode), nil, false) | ||
| st := status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode) | ||
| t.closeStream(s, st.Err(), false, http2.ErrCodeNo, st, nil, false) |
There was a problem hiding this comment.
Where is that conversion happening?
| case *http2.HeadersFrame: | ||
| // When the client creates a stream, write a partial gRPC | ||
| // message followed by an RST_STREAM. | ||
| go func() { |
There was a problem hiding this comment.
Why is this in a goroutine, but the ping ack is written inline?
Also...can we just not reply to the ping and then remove the lock?
There was a problem hiding this comment.
Removed the ping handling and the mutex. Removed the separate goroutine used for writing data frames.
The removed things were unnecessary. I copied the loop that reads frames from an existing test and didn't remove the extra stuff.
grpc-go/internal/transport/transport_test.go
Lines 1414 to 1450 in 950a7cf
Co-authored-by: Doug Fawley <dfawley@google.com>
| case *http2.RSTStreamFrame: | ||
| if frame.Header().StreamID != 1 || http2.ErrCode(frame.ErrCode) != http2.ErrCodeFlowControl { | ||
| t.Errorf("RST stream received with streamID: %d and code: %v, want streamID: 1 and code: http2.ErrCodeFlowControl", frame.Header().StreamID, http2.ErrCode(frame.ErrCode)) | ||
| messageLen := 2048 |
Fixes: #8281
RCA: #8281 (comment)
This PR uses a status error instead of an
io.UnexpectedEOFto fail RPCs that have partially read a gRPC message.RELEASE NOTES:
INTERNALinstead ofCANCELLEDorDEADLINE_EXCEEDEDwhen the client receives an RST_STREAM frame while reading a gRPC message.