gopls中一死锁问题记录 - Go语言中文社区

gopls中一死锁问题记录


死锁表象

client端在发完initialize请求后,gopls调用initialize对应的handler,初始化成功。但是client端在发下一个请求时,gopls就"卡"死了,client端发出去了请求,但是gopls却显示没有收到。而gopls端CPU资源和内存资源占用极低。

调用lsof -i:port(其实从这里就能看出来是gopls创建了两个监听同一端口的goroutine导致的)

COMMAND   PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
gopls   23189 henrywong    3u  IPv6 0x30de821dc8a32b2d      0t0  TCP *:prp (LISTEN)
gopls   23189 henrywong    8u  IPv6 0x30de821dd103c56d      0t0  TCP localhost:prp->localhost:59692 (ESTABLISHED)
node    23203 henrywong  823u  IPv4 0x30de821dd593456d      0t0  TCP localhost:59692->localhost:prp (ESTABLISHED)

pprof

使用pprof来获得关于gopls的goroutine的情况如下,

goroutine 82 [running]:
...

goroutine 1 [IO wait, 11 minutes]:
internal/poll.runtime_pollWait(0x5269f68, 0x72, 0x0)
	/usr/local/opt/go/libexec/src/runtime/netpoll.go:182 +0x56
internal/poll.(*pollDesc).wait(0xc000100598, 0x72, 0x0, 0x0, 0x168d7a0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:87 +0x9b
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:92
internal/poll.(*FD).Accept(0xc000100580, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_unix.go:384 +0x1ba
net.(*netFD).accept(0xc000100580, 0xc000000180, 0x154a558, 0xc0001d1868)
	/usr/local/opt/go/libexec/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc0000c0110, 0xc0001d1880, 0xc0001d1888, 0x28)
	/usr/local/opt/go/libexec/src/net/tcpsock_posix.go:139 +0x32
net.(*TCPListener).Accept(0xc0000c0110, 0x16cfc18, 0xc0001f6000, 0x178aa40, 0xc0000b6008)
	/usr/local/opt/go/libexec/src/net/tcpsock.go:260 +0x48
golang.org/x/tools/internal/lsp.RunServerOnAddress(0x178aa40, 0xc0000b6008, 0x177d880, 0x1bd44b8, 0xc0000b7230, 0x5, 0xc000523b08, 0xc0001d1a10, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/server.go:73 +0x16c
golang.org/x/tools/internal/lsp.RunServerOnPort(0x178aa40, 0xc0000b6008, 0x177d880, 0x1bd44b8, 0x82b, 0xc0001d1b08, 0x0, 0x40)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/server.go:62 +0xd5
golang.org/x/tools/internal/lsp/cmd.(*Serve).Run(0xc0000d6c90, 0x178aa40, 0xc0000b6008, 0xc0000c8040, 0x0, 0x0, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/cmd/serve.go:92 +0x5fe
golang.org/x/tools/internal/tool.Main.func2(0x0, 0x178d140, 0xc0000d6c90, 0x178aa40, 0xc0000b6008, 0xc0000c2d80, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/tool/tool.go:130 +0xb7
golang.org/x/tools/internal/tool.Main(0x178aa40, 0xc0000b6008, 0x178d140, 0xc0000d6c90, 0xc0000c8040, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/tool/tool.go:131 +0x243
golang.org/x/tools/internal/lsp/cmd.(*Application).Run(0xc0000d6c60, 0x178aa40, 0xc0000b6008, 0xc0000c8040, 0x0, 0x0, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/cmd/cmd.go:104 +0x5ed
golang.org/x/tools/internal/tool.Main.func2(0xc0000d6c60, 0x178d100, 0xc0000d6c60, 0x178aa40, 0xc0000b6008, 0xc0000c2d20, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/tool/tool.go:130 +0xb7
golang.org/x/tools/internal/tool.Main(0x178aa40, 0xc0000b6008, 0x178d100, 0xc0000d6c60, 0xc0000c8010, 0x4, 0x4)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/tool/tool.go:131 +0x243
main.main()
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/cmd/gopls/main.go:20 +0xf4

goroutine 6 [semacquire, 11 minutes]:
internal/poll.runtime_Semacquire(0xc0001e6188)
	/usr/local/opt/go/libexec/src/runtime/sema.go:61 +0x39
internal/poll.(*fdMutex).rwlock(0xc0001e6180, 0xc0001cdc01, 0x117eb19)
	/usr/local/opt/go/libexec/src/internal/poll/fd_mutex.go:154 +0xad
internal/poll.(*FD).readLock(...)
	/usr/local/opt/go/libexec/src/internal/poll/fd_mutex.go:221
internal/poll.(*FD).Read(0xc0001e6180, 0xc0001f4000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_unix.go:146 +0x4b
net.(*netFD).Read(0xc0001e6180, 0xc0001f4000, 0x1000, 0x1000, 0x104471c, 0x2, 0x15b29e0)
	/usr/local/opt/go/libexec/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc000010040, 0xc0001f4000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/net/net.go:177 +0x69
bufio.(*Reader).Read(0xc000030300, 0xc00002c690, 0xe4, 0xe4, 0xc0001cdd70, 0x104471c, 0xf0)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:223 +0x22f
io.ReadAtLeast(0x177d440, 0xc000030300, 0xc00002c690, 0xe4, 0xe4, 0xe4, 0x0, 0xc0000c61e0, 0xc0001cde80)
	/usr/local/opt/go/libexec/src/io/io.go:310 +0x88
io.ReadFull(...)
	/usr/local/opt/go/libexec/src/io/io.go:329
golang.org/x/tools/internal/jsonrpc2.(*headerStream).Read(0xc00000e0e0, 0x178aa40, 0xc0000b6008, 0xc0000c6180, 0xc00000e320, 0xc00000e301, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/stream.go:127 +0x6ad
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run(0xc0001f8000, 0x178aa40, 0xc0000b6008, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:281 +0xee
created by golang.org/x/tools/internal/lsp/cmd.(*Serve).Run.func2
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/cmd/serve.go:86 +0xa8

goroutine 20 [IO wait]:
...

goroutine 7 [IO wait, 11 minutes]:
internal/poll.runtime_pollWait(0x5269dc8, 0x72, 0xffffffffffffffff)
	/usr/local/opt/go/libexec/src/runtime/netpoll.go:182 +0x56
internal/poll.(*pollDesc).wait(0xc0001e6198, 0x72, 0xf00, 0xf1c, 0xffffffffffffffff)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:87 +0x9b
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:92
internal/poll.(*FD).Read(0xc0001e6180, 0xc0001f40e4, 0xf1c, 0xf1c, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_unix.go:169 +0x1f2
net.(*netFD).Read(0xc0001e6180, 0xc0001f40e4, 0xf1c, 0xf1c, 0xe4, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc000010040, 0xc0001f40e4, 0xf1c, 0xf1c, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/net/net.go:177 +0x69
bufio.(*Reader).fill(0xc000030300)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:100 +0x10f
bufio.(*Reader).ReadSlice(0xc000030300, 0xc0001aef0a, 0x0, 0x0, 0x164bf20, 0xc0001ee090, 0xc000222000)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:356 +0x3d
bufio.(*Reader).ReadBytes(0xc000030300, 0xa, 0xc0000f5e00, 0xc0001fc480, 0xc0000f5de8, 0x1006f5f, 0xc0000c6240)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:434 +0x70
bufio.(*Reader).ReadString(...)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:474
golang.org/x/tools/internal/jsonrpc2.(*headerStream).Read(0xc00000e0e0, 0x178aa40, 0xc0000b6008, 0xc0000c6240, 0xc00028f6c0, 0xc00028f601, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/stream.go:97 +0x88
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run(0xc0001f8000, 0x178aa40, 0xc0000b6008, 0x0, 0x0)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:281 +0xee
golang.org/x/tools/internal/lsp.(*Server).Run(0xc0001f6000, 0x178aa40, 0xc0000b6008, 0xc0000b7230, 0x5)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/server.go:64 +0x42
created by golang.org/x/tools/internal/lsp.RunServerOnAddress
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/lsp/server.go:81 +0x155

goroutine 34 [chan receive, 11 minutes]:
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run.func1(0xc0000c6180, 0xc0001f8000)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:272 +0x46
created by golang.org/x/tools/internal/jsonrpc2.(*Conn).Run
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:270 +0xba

goroutine 35 [chan receive, 11 minutes]:
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run.func1(0xc0000c6240, 0xc0001f8000)
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:272 +0x46
created by golang.org/x/tools/internal/jsonrpc2.(*Conn).Run
	/Users/henrywong/workspace/gopath/src/golang.org/x/tools/internal/jsonrpc2/jsonrpc2.go:270 +0xba

goroutine 54 [IO wait]:
...

goroutine 83 [IO wait]:
...

goroutine创建示意图如下所示。
gopls goroutine

5个goroutine,其中goroutine 6和goroutine7对应相同的函数 jsonrpc2.go:Run(),两者依赖于同一个stream,

// Listen announces on the local network address.
//
// The network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
//
// For TCP networks, if the host in the address parameter is empty or
// a literal unspecified IP address, Listen listens on all available
// unicast and anycast IP addresses of the local system.
// To only use IPv4, use network "tcp4".
// The address can use a host name, but this is not recommended,
// because it will create a listener for at most one of the host's IP
// addresses.
// If the port in the address parameter is empty or "0", as in
// "127.0.0.1:" or "[::1]:0", a port number is automatically chosen.
// The Addr method of Listener can be used to discover the chosen
// port.
//
// See func Dial for a description of the network and address
// parameters.
func Listen(network, address string) (Listener, error) {
	var lc ListenConfig
	return lc.Listen(context.Background(), network, address)
}

goroutine

问题原因

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/dashuniuniu/article/details/90737540
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢