-
Notifications
You must be signed in to change notification settings - Fork 441
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
Conversation
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") |
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.
Remove references to http
server.go
Outdated
|
||
} | ||
|
||
func (s *Server) shuttingDown() bool { |
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.
Remove unused function
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.
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") |
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.
Change to fatal?
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.
Why or why not
server.go
Outdated
srv.mu.Lock() | ||
activeConns := len(srv.activeConn) | ||
srv.mu.Unlock() | ||
if activeConns == 0 { |
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.
Refactor activeConn check into function?
server.go
Outdated
for { | ||
|
||
srv.mu.Lock() | ||
activeConns := len(srv.activeConn) |
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.
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") |
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.
Why or why not
@shazow quick 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.
- 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
andgetDoneChan
)
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) |
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.
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, |
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.
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.
Most of the code is an exact copy of net/http/server.go.
closes: #22