-
Notifications
You must be signed in to change notification settings - Fork 4k
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
enforce to close accepted connection after processing #2883
base: master
Are you sure you want to change the base?
Conversation
lib/go/thrift/simple_server.go
Outdated
@@ -211,6 +211,10 @@ func (p *TSimpleServer) innerAccept() (int32, error) { | |||
select { | |||
case <-ctx.Done(): | |||
// client exited, do nothing | |||
if client != nil { | |||
client.Close() |
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.
can you explain more why do we need to close the client here? is there any connection leak otherwise?
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.
Yes, if the call to Close is not called, then any dynamically allocated data in client object is lost forever and hence the caller's golang runtime keeps eating memory.
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.
How would that affect overall performance, e.g. when doing multiple calls?
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.
Could you help clarify what is your overall performance concern?
Below is my understanding of how the simpleServer works with its serverTransport regarding accept an incoming request. Please correct me if I miss anything.
A client object is created by calling the underlying serverTransport.Accept(). I think client.Close() is to signal serverTransport that thrift server has finished using this client. So serverTransport could do whatever is required on its part, either to cleanup or recycle the object for reuse.
Without the signal from thrift server, what is expected from serverTransport to manage client object created by itself? The reference to client is lost after processing the request.
I guess thrift simple server has some assumption on how serverTransport to manage client created by serverTransport itself. Could you help advise where I could find the assumption? Or help explain the choice why not to enforce close client after processing.
Thanks for helping to review.
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.
I simply asked a question. If your answer is a validated "No it will not affect perf because ..." that's fine with me.
lib/go/thrift/simple_server.go
Outdated
@@ -270,6 +274,7 @@ func (p *TSimpleServer) Stop() error { | |||
} | |||
|
|||
<-ctx.Done() | |||
p.stopChan = nil |
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.
this does nothing, it's immediately overwritten by the next line
lib/go/thrift/simple_server.go
Outdated
@@ -356,6 +361,7 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { | |||
ok, err := processor.Process(ctx, inputProtocol, outputProtocol) | |||
if errors.Is(err, ErrAbandonRequest) { | |||
err := client.Close() | |||
client = nil |
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.
this does not work as you expected.
here client
is the local arg of processRequests
function, setting it to nil
only affects that copy of client
. it does not affect the client
you are checking on line 214, which is at the caller of processRequests
.
the whole nil checking regarding client is also unnecessary, if client
is already closed, closing it again will only give you an already closed error, which you ignored anyways (on line 215).
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.
Makes sense. Then is it good to have defer client.Close
in processRequests()?
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.
I would prefer to defer it in innerAccept
instead.
please fix the failed unit test. |
@fishy I updated to fix golang unit test. Now I see there is build error due to python test. I dont understand how that is related to my changes. Could you help me understand what I need to fix? |
@jshen14 sorry I missed your comment last year 😓 please rebase your change on top of latest master branch and the python tests should be fixed now. |
Enforce close of accepted connection in golang simple server to avoid memory leak
[skip ci]
anywhere in the commit message to free up build resources.