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

remotedb/grpcdb: fix net.Listener leak in ListenAndServe #269

Conversation

odeke-em
Copy link

Uses Go's named return value feature to properly check and
ensure that if any error is encountered, that we properly
invoke .Close for the bound net listener inside of ListenAndServe.

Fixes #268

Uses Go's named return value feature to properly check and
ensure that if any error is encountered, that we properly
invoke .Close for the bound net listener inside of ListenAndServe.

Fixes tendermint#268
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
defer func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some reason we shouldn't simply defer the close unconditionally? This function blocks until the server terminates anyway, and we're not checking the result of the Close call anyway.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes:

  1. It is the simplest and most non-invasive fix, as I've pushed up :-)
  2. If at all NewServer returns a value whose .Serve method has goroutines that might do other work on the listener, or also later on invokes .Close on the listener, that could cause problems and the biggest one being an already closed error being reported (something that I've seen in many code bases)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The listener is created in this scope, it cannot be closed anywhere else.

Copy link

@tychoish tychoish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that this works.

Additionally this database implementation is not, as far as I know ever used, and in light of that, I would be more comfortable deleting it rather than attempting to fix it, but if there are production users, then we can pursue this more.

@@ -16,11 +16,17 @@ import (
// ListenAndServe is a blocking function that sets up a gRPC based
// server at the address supplied, with the gRPC options passed in.
// Normally in usage, invoke it in a goroutine like you would for http.ListenAndServe.
func ListenAndServe(addr, cert, key string, opts ...grpc.ServerOption) error {
func ListenAndServe(addr, cert, key string, opts ...grpc.ServerOption) (rerr error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain how rerr is ever mutated so that line 25 could ever be true?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go has a feature called "named results" https://go.dev/ref/spec#Function_types whereby if you name a return value, in a defer you can check against that value so what the last return set will now be captured by that return.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return at the end sets it. (Normal returns also set named return values)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codecov
Copy link

codecov bot commented Jun 28, 2022

Codecov Report

Merging #269 (bbd5a76) into master (b3c748f) will decrease coverage by 0.12%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #269      +/-   ##
==========================================
- Coverage   68.54%   68.41%   -0.13%     
==========================================
  Files          27       27              
  Lines        2130     2134       +4     
==========================================
  Hits         1460     1460              
- Misses        595      599       +4     
  Partials       75       75              
Impacted Files Coverage Δ
remotedb/grpcdb/server.go 0.00% <0.00%> (ø)
Impacted Files Coverage Δ
remotedb/grpcdb/server.go 0.00% <0.00%> (ø)

@odeke-em
Copy link
Author

@tychoish thanks for the review! In regards to deleting code, I think perhaps I can leave that decision to the maintainers, I am just fixing security issues that I identified.

@creachadair
Copy link
Contributor

creachadair commented Jun 28, 2022

I don't know that this works.

Additionally this database implementation is not, as far as I know ever used, and in light of that, I would be more comfortable deleting it rather than attempting to fix it, but if there are production users, then we can pursue this more.

It's difficult to tell. A cursory search on cs.github.com doesn't turn up any obvious uses, and if that's properly indicative it suggests maybe the whole remotedb package could go. But I think there are some applications that are using tm-db directly and not only through Tendermint & the SDK. Anyway, the change is safe to make.

@odeke-em odeke-em requested a review from tychoish June 28, 2022 13:03
@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the Stale label Jul 20, 2022
@github-actions github-actions bot closed this Jul 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

remotedb/grpcdb: a net.Listener leaks if ListenAndServe's NewServer or srv.Serve errors in any way
3 participants