Skip to content

Commit 181bc90

Browse files
committed
don't block on connection close
1 parent 43cd707 commit 181bc90

File tree

4 files changed

+18
-16
lines changed

4 files changed

+18
-16
lines changed

const.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (e *GoAwayError) Temporary() bool {
4545

4646
func (e *GoAwayError) Is(target error) bool {
4747
// to maintain compatibility with errors returned by previous versions
48-
if e.Remote && target == ErrRemoteGoAway {
48+
if e.Remote && target == ErrRemoteGoAwayNormal {
4949
return true
5050
} else if !e.Remote && target == ErrSessionShutdown {
5151
return true
@@ -111,8 +111,8 @@ var (
111111
// ErrUnexpectedFlag is set when we get an unexpected flag
112112
ErrUnexpectedFlag = &Error{msg: "unexpected flag"}
113113

114-
// ErrRemoteGoAway is used when we get a go away from the other side
115-
ErrRemoteGoAway = &GoAwayError{Remote: true, ErrorCode: goAwayNormal}
114+
// ErrRemoteGoAwayNormal is used when we get a go away from the other side
115+
ErrRemoteGoAwayNormal = &GoAwayError{Remote: true, ErrorCode: goAwayNormal}
116116

117117
// ErrStreamReset is sent if a stream is reset. This can happen
118118
// if the backlog is exceeded, or if there was a remote GoAway.

session.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ var nullMemoryManager = &nullMemoryManagerImpl{}
4646
type Session struct {
4747
rtt int64 // to be accessed atomically, in nanoseconds
4848

49-
// remoteGoAway indicates the remote side does
49+
// remoteGoAwayNormal indicates the remote side does
5050
// not want futher connections. Must be first for alignment.
51-
remoteGoAway int32
51+
remoteGoAwayNormal int32
5252

5353
// localGoAway indicates that we should stop
5454
// accepting futher connections. Must be first for alignment.
@@ -205,8 +205,8 @@ func (s *Session) OpenStream(ctx context.Context) (*Stream, error) {
205205
if s.IsClosed() {
206206
return nil, s.shutdownErr
207207
}
208-
if atomic.LoadInt32(&s.remoteGoAway) == 1 {
209-
return nil, ErrRemoteGoAway
208+
if atomic.LoadInt32(&s.remoteGoAwayNormal) == 1 {
209+
return nil, ErrRemoteGoAwayNormal
210210
}
211211

212212
// Block if we have too many inflight SYNs
@@ -285,15 +285,15 @@ func (s *Session) AcceptStream() (*Stream, error) {
285285
}
286286
}
287287

288-
// Close is used to close the session and all streams.
289-
// Attempts to send a GoAway before closing the connection. The GoAway may not actually be sent depending on the
290-
// semantics of the underlying net.Conn. For TCP connections, it may be dropped depending on LINGER value or
291-
// if there's unread data in the kernel receive buffer.
288+
// Close is used to close the session and all streams. It doesn't send a GoAway before
289+
// closing the connection.
292290
func (s *Session) Close() error {
293291
return s.close(ErrSessionShutdown, false, goAwayNormal)
294292
}
295293

296294
// CloseWithError is used to close the session and all streams after sending a GoAway message with errCode.
295+
// Blocks for ConnectionWriteTimeout to write the GoAway message.
296+
//
297297
// The GoAway may not actually be sent depending on the semantics of the underlying net.Conn.
298298
// For TCP connections, it may be dropped depending on LINGER value or if there's unread data in the kernel
299299
// receive buffer.
@@ -315,7 +315,8 @@ func (s *Session) close(shutdownErr error, sendGoAway bool, errCode uint32) erro
315315
close(s.shutdownCh)
316316
s.stopKeepalive()
317317

318-
if sendGoAway {
318+
// Only send GoAway if we have an error code.
319+
if sendGoAway && errCode != goAwayNormal {
319320
// wait for write loop to exit
320321
// We need to write the current frame completely before sending a goaway.
321322
// This will wait for at most s.config.ConnectionWriteTimeout
@@ -814,7 +815,7 @@ func (s *Session) handleGoAway(hdr header) error {
814815
code := hdr.Length()
815816
switch code {
816817
case goAwayNormal:
817-
atomic.SwapInt32(&s.remoteGoAway, 1)
818+
atomic.SwapInt32(&s.remoteGoAwayNormal, 1)
818819
// Don't close connection on normal go away. Let the existing streams
819820
// complete gracefully.
820821
return nil

session_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ func TestGoAway(t *testing.T) {
651651
switch err {
652652
case nil:
653653
s.Close()
654-
case ErrRemoteGoAway:
654+
case ErrRemoteGoAwayNormal:
655655
return
656656
default:
657657
t.Fatalf("err: %v", err)

stream.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func (s *Stream) CloseWrite() error {
310310
return nil
311311
case halfReset:
312312
s.stateLock.Unlock()
313-
return ErrStreamReset
313+
return s.writeErr
314314
default:
315315
panic("invalid state")
316316
}
@@ -331,7 +331,8 @@ func (s *Stream) CloseWrite() error {
331331
return err
332332
}
333333

334-
// CloseRead is used to close the stream for writing.
334+
// CloseRead is used to close the stream for reading.
335+
// Note: Remote is not notified.
335336
func (s *Stream) CloseRead() error {
336337
cleanup := false
337338
s.stateLock.Lock()

0 commit comments

Comments
 (0)