Skip to content

Commit 989f6e9

Browse files
FZambiaC-Pro
andauthored
Fix panic due to nil queue upon close (#112) (#113)
Co-authored-by: Sergey Melekhin <[email protected]>
1 parent 653f7dd commit 989f6e9

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

client.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,8 +769,12 @@ func (c *Client) reader(t transport, disconnectCh chan struct{}) {
769769
}
770770

771771
func (c *Client) runHandlerSync(fn func()) {
772-
waitCh := make(chan struct{})
773772
c.mu.RLock()
773+
if c.cbQueue == nil {
774+
c.mu.RUnlock()
775+
return
776+
}
777+
waitCh := make(chan struct{})
774778
c.cbQueue.push(func(delay time.Duration) {
775779
defer close(waitCh)
776780
fn()
@@ -780,9 +784,15 @@ func (c *Client) runHandlerSync(fn func()) {
780784
}
781785

782786
func (c *Client) runHandlerAsync(fn func()) {
787+
c.mu.RLock()
788+
if c.cbQueue == nil {
789+
c.mu.RUnlock()
790+
return
791+
}
783792
c.cbQueue.push(func(delay time.Duration) {
784793
fn()
785794
})
795+
c.mu.RUnlock()
786796
}
787797

788798
func (c *Client) handle(reply *protocol.Reply) {

client_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,32 @@ func TestSubscription_Unsubscribe(t *testing.T) {
334334
select {
335335
case <-unsubscribedCh:
336336
case <-time.After(3 * time.Second):
337-
t.Errorf("timeout waiting for subscribe")
337+
t.Errorf("timeout waiting for unsubscribe")
338+
}
339+
}
340+
341+
func TestConcurrentCloseDisconnect(t *testing.T) {
342+
// Race condition probability between close and disconnect is small,
343+
// so doing a lot of iterations increase chance of reproducing.
344+
for i := 0; i < 100; i++ {
345+
client := NewJsonClient("ws://localhost:8000/connection/websocket", Config{})
346+
client.OnConnecting(func(ConnectingEvent) {})
347+
if err := client.Connect(); err != nil {
348+
t.Fatalf("failed to connect: %v", err)
349+
}
350+
sub, err := client.NewSubscription("thechannel", SubscriptionConfig{})
351+
if err != nil {
352+
t.Fatalf("failed to subscribe: %v", err)
353+
}
354+
sub.OnUnsubscribed(func(UnsubscribedEvent) {})
355+
sub.OnSubscribing(func(SubscribingEvent) {})
356+
_ = sub.Subscribe()
357+
go client.Close()
358+
client.handleDisconnect(&disconnect{
359+
Code: connectingTransportClosed,
360+
Reason: "transport closed",
361+
Reconnect: false,
362+
})
338363
}
339364
}
340365

0 commit comments

Comments
 (0)