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

optimize: the graceful shutdown logic to avoid errors when a connection in idle state receives new requests after being closed #382

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions connection_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type connection struct {
maxSize int // The maximum size of data between two Release().
bookSize int // The size of data that can be read at once.
state connState // Connection state should be changed sequentially.
wasIdle bool // It's for double checking a conn is really idle, avoiding closing a conn that may receive traffic immediately.
}

var (
Expand Down
6 changes: 0 additions & 6 deletions connection_onevent.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ func disableGopool() error {

// ------------------------------------ implement OnPrepare, OnRequest, CloseCallback ------------------------------------

type gracefulExit interface {
isIdle() (yes bool)
Close() (err error)
}

// onEvent is the collection of event processing.
// OnPrepare, OnRequest, CloseCallback share the lock processing,
// which is a CAS lock and can only be cleared by OnRequest.
Expand Down Expand Up @@ -310,7 +305,6 @@ func (c *connection) register() (err error) {
return nil
}

// isIdle implements gracefulExit.
func (c *connection) isIdle() (yes bool) {
return c.isUnlock(processing) &&
c.inputBuffer.IsEmpty() &&
Expand Down
12 changes: 8 additions & 4 deletions netpoll_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ func (s *server) Close(ctx context.Context) error {
for {
activeConn := 0
s.connections.Range(func(key, value interface{}) bool {
conn, ok := value.(gracefulExit)
conn, ok := value.(*connection)
if !ok || conn.isIdle() {
value.(Connection).Close()
if conn.wasIdle {
value.(Connection).Close()
} else {
conn.wasIdle = true
}
} else {
activeConn++
}
Expand All @@ -83,8 +87,8 @@ func (s *server) Close(ctx context.Context) error {
waitTime := time.Millisecond * time.Duration(activeConn)
if waitTime > time.Second { // max wait time is 1000 ms
waitTime = time.Millisecond * 1000
} else if waitTime < time.Millisecond*50 { // min wait time is 50 ms
waitTime = time.Millisecond * 50
} else if waitTime < time.Millisecond*200 { // min wait time is 200 ms
waitTime = time.Millisecond * 200
}
select {
case <-ctx.Done():
Expand Down
Loading