Skip to content

Commit 2f52ea1

Browse files
authored
Merge pull request #172 from rabbitmq/lukebakken/nil-for-cleanup
Set channels and allocator to nil in shutdown
2 parents 30f5d55 + 190c143 commit 2f52ea1

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

client_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,41 @@ func TestOpen(t *testing.T) {
288288
if c, err := Open(rwc, defaultConfig()); err != nil {
289289
t.Fatalf("could not create connection: %v (%s)", c, err)
290290
}
291+
}
292+
293+
func TestOpenClose_ShouldNotPanic(t *testing.T) {
294+
rwc, srv := newSession(t)
295+
t.Cleanup(func() {
296+
_ = rwc.Close()
297+
})
298+
299+
go func() {
300+
srv.connectionOpen()
301+
srv.connectionClose()
302+
}()
303+
304+
c, err := Open(rwc, defaultConfig())
305+
if err != nil {
306+
t.Fatalf("could not create connection: %v (%s)", c, err)
307+
}
308+
309+
if err := c.Close(); err != nil {
310+
t.Fatalf("could not close connection: %s", err)
311+
}
291312

313+
defer func() {
314+
if r := recover(); r != nil {
315+
t.Fatalf("creating a channel on a closed connection should not panic: %s", r)
316+
}
317+
}()
318+
319+
ch, err := c.Channel()
320+
if ch != nil {
321+
t.Fatalf("creating a channel on a closed connection should not succeed: %v, (%s)", ch, err)
322+
}
323+
if err != ErrClosed {
324+
t.Fatalf("error should be closed: %s", err)
325+
}
292326
}
293327

294328
func TestChannelOpen(t *testing.T) {

connection.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,8 @@ func (c *Connection) shutdown(err *Error) {
551551

552552
c.conn.Close()
553553

554-
c.channels = map[uint16]*Channel{}
555-
c.allocator = newAllocator(1, c.Config.ChannelMax)
554+
c.channels = nil
555+
c.allocator = nil
556556
c.noNotify = true
557557
})
558558
}
@@ -770,8 +770,10 @@ func (c *Connection) releaseChannel(id uint16) {
770770
c.m.Lock()
771771
defer c.m.Unlock()
772772

773-
delete(c.channels, id)
774-
c.allocator.release(int(id))
773+
if !c.IsClosed() {
774+
delete(c.channels, id)
775+
c.allocator.release(int(id))
776+
}
775777
}
776778

777779
// openChannel allocates and opens a channel, must be paired with closeChannel
@@ -919,13 +921,17 @@ func (c *Connection) openTune(config Config, auth Authentication) error {
919921
// Edge case that may race with c.shutdown()
920922
// https://github.com/rabbitmq/amqp091-go/issues/170
921923
c.m.Lock()
924+
922925
// When the server and client both use default 0, then the max channel is
923926
// only limited by uint16.
924927
c.Config.ChannelMax = pick(config.ChannelMax, int(tune.ChannelMax))
925928
if c.Config.ChannelMax == 0 {
926929
c.Config.ChannelMax = defaultChannelMax
927930
}
928931
c.Config.ChannelMax = min(c.Config.ChannelMax, maxChannelMax)
932+
933+
c.allocator = newAllocator(1, c.Config.ChannelMax)
934+
929935
c.m.Unlock()
930936

931937
// Frame size includes headers and end byte (len(payload)+8), even if
@@ -982,9 +988,6 @@ func (c *Connection) openComplete() error {
982988
_ = deadliner.SetDeadline(time.Time{})
983989
}
984990

985-
c.m.Lock()
986-
c.allocator = newAllocator(1, c.Config.ChannelMax)
987-
c.m.Unlock()
988991
return nil
989992
}
990993

0 commit comments

Comments
 (0)