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
xdsclient: fix LRS stream leaks when errors are encountered #5505
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import ( | |
"context" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"time" | ||
|
||
"github.com/golang/protobuf/proto" | ||
|
@@ -59,7 +60,11 @@ func (v2c *client) SendFirstLoadStatsRequest(s grpc.ClientStream) error { | |
|
||
req := &lrspb.LoadStatsRequest{Node: node} | ||
v2c.logger.Infof("lrs: sending init LoadStatsRequest: %v", pretty.ToJSON(req)) | ||
return stream.Send(req) | ||
err := stream.Send(req) | ||
if err == io.EOF { | ||
return getStreamError(stream) | ||
} | ||
return err | ||
} | ||
|
||
func (v2c *client) HandleLoadStatsResponse(s grpc.ClientStream) ([]string, time.Duration, error) { | ||
|
@@ -149,5 +154,17 @@ func (v2c *client) SendLoadStatsRequest(s grpc.ClientStream, loads []*load.Data) | |
|
||
req := &lrspb.LoadStatsRequest{ClusterStats: clusterStats} | ||
v2c.logger.Infof("lrs: sending LRS loads: %+v", pretty.ToJSON(req)) | ||
return stream.Send(req) | ||
err := stream.Send(req) | ||
if err == io.EOF { | ||
return getStreamError(stream) | ||
} | ||
return err | ||
} | ||
|
||
func getStreamError(stream lrsStream) error { | ||
for { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should there be a way for this for loop to terminate other than when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if _, err := stream.Recv(); err != nil { | ||
return err | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/getStreamError/getStreamRecvError/?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is trying to achieve?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error returned from
Send
is only everio.EOF
in the event of the server terminating the stream or a connection loss. This function receives the actual error from the stream.grpc-go/stream.go
Lines 108 to 110 in 6417495
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
Recv
always supposed to contain a more informational error on the client side, even if the error was encountered on the client? I'm thinking about the case where the error forSend
happens on the client, but we still end up using the error we get fromRecv
. Is it possible that the former contained more contextual information?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My question is whether we should do this only when
Send
returns an error which is noio.EOF
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. Yes, that's a good idea: done.