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

Add support for cleanly shutting down a server #23

Closed
wants to merge 12 commits into from

Conversation

belak
Copy link
Collaborator

@belak belak commented Feb 6, 2017

This is related to #22 and #20 and is needed to write tests.

I understand this is probably more complicated than we were hoping, so feel free to offer suggestions for improvements.

Please do not merge this until I get a chance to double check stuff and clean it up.

@belak
Copy link
Collaborator Author

belak commented Feb 7, 2017

Maybe something like srv.Shutdown(ctx) should be used (see https://tylerchr.blog/golang-18-whats-coming/)

server.go Outdated
}

// getKillChan is used to get or create the kill channel
func (srv *Server) getKillChan() chan struct{} {

Choose a reason for hiding this comment

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

Why would we make this seem like magic instead of having an explicit initialization of the killChan? It seems like this could result in somebody not realizing there are side-effects here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I generally agree, but I'm also a lot more tolerant when it comes to internal APIs for small projects.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is also similar to what net/http does. The locks and such are used more there because it's more complicated, but the general idea is the same. A large portion of this takes inspiration from there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, but also thanks for reviewing @mark-adams !

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that I've read the full source, I think it does makes sense to not have this (or getDoneChan) and instead initialize in the one place these are called: when entering stateStarted in Serve().

server.go Outdated
}

// getKillChan is used to get or create the wait group
func (srv *Server) getWaitGroup() *sync.WaitGroup {
Copy link
Contributor

Choose a reason for hiding this comment

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

Like Mutex, a WaitGroup can be used as an empty value. Even the example does it this way: https://golang.org/pkg/sync/#example_WaitGroup

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've removed this helper function, but I still think it should be a pointer, otherwise there's a race condition between shutting down a server and starting a new one with the same Server object.

srv.listener = nil

// Grab the waitgroup then unlock
wg := srv.wg
Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be necessary once changed to a value.

server.go Outdated
}
}

// getKillChan is used to get or create the done channel
Copy link
Contributor

@progrium progrium Feb 14, 2017

Choose a reason for hiding this comment

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

Comment name discrepancy. (Though irrelevant if removed)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

All these helpers have been removed.

server.go Outdated
}

// getKillChan is used to get or create the kill channel
func (srv *Server) getKillChan() chan struct{} {
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that I've read the full source, I think it does makes sense to not have this (or getDoneChan) and instead initialize in the one place these are called: when entering stateStarted in Serve().

srv.listener = nil

// Grab the waitgroup then unlock
wg := srv.wg
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

@belak belak changed the title [WIP] Add support for cleanly shutting down a server Add support for cleanly shutting down a server Feb 15, 2017
@belak
Copy link
Collaborator Author

belak commented Feb 15, 2017

Once we agree on the general method, I'll add some tests.

@belak
Copy link
Collaborator Author

belak commented Feb 15, 2017

Note to self: there's a small issue currently around the state getting set to stateClosing while the server is still draining.

EDIT: fixed

@belak
Copy link
Collaborator Author

belak commented Mar 9, 2017

There's a race condition somewhere (no surprise there) and the tests are failing sometimes.

server_test.go:69: wait: remote command exited without exit status or exit signal

Ideas would be appreciated.

@progrium
Copy link
Contributor

Shall we close in favor of #34?

@belak
Copy link
Collaborator Author

belak commented Apr 28, 2017

That's probably the best move. I'd like to get this in as it doesn't rely on polling to shut down, but the other method should work.

@belak belak closed this Apr 28, 2017
@progrium
Copy link
Contributor

Okay, well thanks for the contribution in any case and instigating a solution for this.

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

Successfully merging this pull request may close these issues.

None yet

3 participants