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

server: first pass at Shutdown and Close #34

Merged
merged 3 commits into from
May 22, 2017
Merged

server: first pass at Shutdown and Close #34

merged 3 commits into from
May 22, 2017

Conversation

mattatcha
Copy link
Member

Most of the code is an exact copy of net/http/server.go.

closes: #22

server.go Outdated
"time"

gossh "golang.org/x/crypto/ssh"
)

// ErrServerClosed is returned by the Server's Serve, ListenAndServe,
// and ListenAndServeTLS methods after a call to Shutdown or Close.
var ErrServerClosed = errors.New("http: Server closed")
Copy link
Member Author

Choose a reason for hiding this comment

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

Remove references to http

server.go Outdated

}

func (s *Server) shuttingDown() bool {
Copy link
Member Author

Choose a reason for hiding this comment

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

Remove unused function

Copy link
Collaborator

Choose a reason for hiding this comment

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

If this is removed, we don't need s.inShutdown at all.

server_test.go Outdated
timeout := time.After(time.Millisecond * 100)
select {
case <-timeout:
t.Error("timeout")
Copy link
Member Author

Choose a reason for hiding this comment

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

Change to fatal?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why or why not

server.go Outdated
srv.mu.Lock()
activeConns := len(srv.activeConn)
srv.mu.Unlock()
if activeConns == 0 {
Copy link
Member Author

Choose a reason for hiding this comment

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

Refactor activeConn check into function?

server.go Outdated
for {

srv.mu.Lock()
activeConns := len(srv.activeConn)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since there are no idle connections, maybe we just call them conns?

server_test.go Outdated
timeout := time.After(time.Millisecond * 100)
select {
case <-timeout:
t.Error("timeout")
Copy link
Contributor

Choose a reason for hiding this comment

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

Why or why not

@progrium
Copy link
Contributor

@shazow quick review?

Copy link
Member

@shazow shazow left a comment

Choose a reason for hiding this comment

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

  • Don't think the inShutdown atomic counter is necessary
  • I'm not sure the *Locked vs non-Locked functions are helpful? Both variants are used equally much in random places. (e.g. getDoneChanLocked and getDoneChan)

server.go Outdated
// If the provided context expires before the shutdown is complete,
// then the context's error is returned.
func (srv *Server) Shutdown(ctx context.Context) error {
atomic.AddInt32(&srv.inShutdown, 1)
Copy link
Member

Choose a reason for hiding this comment

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

Any reason to do this atomically rather than inside of the mu mutex?

(Also looks like inShutdown is not needed anyways?)

// shutdownPollInterval is how often we poll for quiescence
// during Server.Shutdown. This is lower during tests, to
// speed up tests.
// Ideally we could find a solution that doesn't involve polling,
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear to me why polling is necessary? Are we waiting for all of the clients to successfully disconnect before Close() returns? Is this a requirement?

In my code, I typically disable the server from accepting new connections and then in separate goroutine(s) I start issuing disconnect orders/closing connections while the original goroutine just returns.

@mattatcha mattatcha changed the title [WIP] server: first pass at Shutdown and Close server: first pass at Shutdown and Close Apr 20, 2017
@progrium progrium merged commit b47c6da into master May 22, 2017
@progrium progrium deleted the close-shutdown branch January 8, 2018 17:02
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.

Add a way to drain incoming connections
4 participants