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

Websocket.Shutdown() leaks resources #737

Open
ydm opened this issue Aug 4, 2021 · 1 comment
Open

Websocket.Shutdown() leaks resources #737

ydm opened this issue Aug 4, 2021 · 1 comment

Comments

@ydm
Copy link
Contributor

ydm commented Aug 4, 2021

Few issues with Websocket.Shutdown():

  1. Websocket.ToRoutine channel is never closed.
  2. During Websocket.Shutdown() the ShutdownC channel is recreated (~websocket.go:398), which endangers all <-ws.ShutdownC calls.
  3. After Websocket.Shutdown() there is a number of leaked gouroutines:
(dlv) gr
Thread 128647 at /usr/lib/go/src/runtime/sys_linux_amd64.s:580
Goroutine 147:
	Runtime: /usr/lib/go/src/runtime/proc.go:337 runtime.gopark (0x44add5)
	User: /usr/lib/go/src/runtime/sema.go:71 sync.runtime_SemacquireMutex (0x481227)
	Go: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:294 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).connectionMonitor (0xc7f5db)
	Start: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:294 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).connectionMonitor.func1 (0xc883e0)

(dlv) bt
0  0x000000000044add5 in runtime.gopark
   at /usr/lib/go/src/runtime/proc.go:337
1  0x000000000044ae93 in runtime.goparkunlock
   at /usr/lib/go/src/runtime/proc.go:342
2  0x000000000045dac8 in runtime.semacquire1
   at /usr/lib/go/src/runtime/sema.go:144
3  0x0000000000481227 in sync.runtime_SemacquireMutex
   at /usr/lib/go/src/runtime/sema.go:71
4  0x00000000004b5045 in sync.(*Mutex).lockSlow
   at /usr/lib/go/src/sync/mutex.go:138
5  0x00000000004b4d76 in sync.(*Mutex).Lock
   at /usr/lib/go/src/sync/mutex.go:81
6  0x0000000000c7e715 in github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).Connect
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:176
7  0x0000000000c88685 in github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).connectionMonitor.func1
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:338
8  0x0000000000484fe1 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:1371
(dlv) gr
Thread 128647 at /usr/lib/go/src/runtime/sys_linux_amd64.s:580
Goroutine 163:
	Runtime: /usr/lib/go/src/runtime/proc.go:337 runtime.gopark (0x44add5)
	User: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/orderbook/node.go:99 github.com/thrasher-corp/gocryptotrader/exchanges/orderbook.(*stack).cleaner (0xacb1d2)
	Go: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/orderbook/node.go:39 github.com/thrasher-corp/gocryptotrader/exchanges/orderbook.newStack (0xacac2e)
	Start: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/orderbook/node.go:96 github.com/thrasher-corp/gocryptotrader/exchanges/orderbook.(*stack).cleaner (0xacb160)
(dlv) bt
0  0x000000000044add5 in runtime.gopark
   at /usr/lib/go/src/runtime/proc.go:337
1  0x000000000040f6c6 in runtime.chanrecv
   at /usr/lib/go/src/runtime/chan.go:576
2  0x000000000040f42b in runtime.chanrecv2
   at /usr/lib/go/src/runtime/chan.go:444
3  0x0000000000acb1d2 in github.com/thrasher-corp/gocryptotrader/exchanges/orderbook.(*stack).cleaner
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/orderbook/node.go:99
4  0x0000000000484fe1 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:1371
Goroutine 199:
	Runtime: /usr/lib/go/src/runtime/proc.go:337 runtime.gopark (0x44add5)
	User: /usr/lib/go/src/runtime/sema.go:56 sync.runtime_Semacquire (0x481105)
	Go: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:477 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor (0xc808e7)
	Start: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:477 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1 (0xc88f40)
(dlv) bt
0  0x000000000044add5 in runtime.gopark
   at /usr/lib/go/src/runtime/proc.go:337
1  0x000000000044ae93 in runtime.goparkunlock
   at /usr/lib/go/src/runtime/proc.go:342
2  0x000000000045dac8 in runtime.semacquire1
   at /usr/lib/go/src/runtime/sema.go:144
3  0x0000000000481105 in sync.runtime_Semacquire
   at /usr/lib/go/src/runtime/sema.go:56
4  0x00000000004b7a14 in sync.(*WaitGroup).Wait
   at /usr/lib/go/src/sync/waitgroup.go:130
5  0x0000000000c7fb65 in github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).Shutdown
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:397
6  0x0000000000c89288 in github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:510
7  0x0000000000484fe1 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:1371
(dlv) gr
Thread 128647 at /usr/lib/go/src/runtime/sys_linux_amd64.s:580
Goroutine 210:
	Runtime: /usr/lib/go/src/runtime/proc.go:337 runtime.gopark (0x44add5)
	User: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:526 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1.1 (0xc88f25)
	Go: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:524 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1 (0xc8959c)
	Start: /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:524 github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1.1 (0xc88ee0)
(dlv) bt
0  0x000000000044add5 in runtime.gopark
   at /usr/lib/go/src/runtime/proc.go:337
1  0x000000000040eb37 in runtime.chansend
   at /usr/lib/go/src/runtime/chan.go:257
2  0x000000000040e915 in runtime.chansend1
   at /usr/lib/go/src/runtime/chan.go:143
3  0x0000000000c88f25 in github.com/thrasher-corp/gocryptotrader/exchanges/stream.(*Websocket).trafficMonitor.func1.1
   at /home/d/go/src/github.com/ydm/gocryptotrader/exchanges/stream/websocket.go:526
4  0x0000000000484fe1 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:1371

I think every long running software should be very careful with resource management.

I don't know what's on purpose and what's not, but it would be great if you come up with a plan on how to handle that and take action towards improving (and hopefully simplifying) websockets.

@thrasher-
Copy link
Collaborator

Thanks for reporting the above @ydm! An improper shutdown can be triggered by disabling an exchanges websocket connection via gctcli. When tested on Binance, it attempts to shutdown but then gets stuck:

[DEBUG] | WEBSOCKET | 18/08/2021 10:21:02 | Binance websocket: running connection monitor cycle
[DEBUG] | WEBSOCKET | 18/08/2021 10:21:02 | Binance websocket: connectionMonitor - websocket disabled, shutting down
[DEBUG] | WEBSOCKET | 18/08/2021 10:21:02 | Binance websocket: shutting down websocket

The internal state still has the connection as enabled

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants