Skip to content

x/tools/gopls: deadlock opening many files at once #32910

Closed
@muirdm

Description

@muirdm

While testing a different issue I ran into a new deadlock. I think it boils down to a different lock acquisition order in these two code paths:

Path 1:

  1. loadParseTypecheck acquires mcache mutex
  2. eventually gets into lsp/cache.(*fileBase).Handle which acquires f.handleMu

Path 2:

  1. lsp/cache.(*goFile).invalidateContent acquires f.handleMu and then tries acquiring mcache mutex.

Here is the full goroutine trace:

goroutine profile: total 100
91 @ 0x1030c0f 0x10078aa 0x1007880 0x100756b 0x131ad28 0x105d841
#	0x131ad27	golang.org/x/tools/internal/jsonrpc2.(*Conn).Run.func1+0x37	/Users/muir/projects/tools/internal/jsonrpc2/jsonrpc2.go:429

1 @ 0x1030c0f 0x10078aa 0x1007880 0x100756b 0x1525c69 0x1525968 0x138755a 0x1388d99 0x1367907 0x15269bc 0x15269ab 0x1525f40 0x1525968 0x138755a 0x1388d99 0x1367907 0x15269bc 0x15269ab 0x1525f40 0x105d841
#	0x1525c68	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x1a8		/Users/muir/projects/tools/internal/lsp/cache/check.go:59
#	0x1525967	golang.org/x/tools/internal/lsp/cache.(*importer).Import+0x87		/Users/muir/projects/tools/internal/lsp/cache/check.go:41
#	0x1387559	go/types.(*Checker).importPackage+0x6e9					/usr/local/go/src/go/types/resolver.go:161
#	0x1388d98	go/types.(*Checker).collectObjects+0x15f8				/usr/local/go/src/go/types/resolver.go:256
#	0x1367906	go/types.(*Checker).checkFiles+0x96					/usr/local/go/src/go/types/check.go:252
#	0x15269bb	go/types.(*Checker).Files+0x9db						/usr/local/go/src/go/types/check.go:245
#	0x15269aa	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0x9ca	/Users/muir/projects/tools/internal/lsp/cache/check.go:187
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f		/Users/muir/projects/tools/internal/lsp/cache/check.go:68
#	0x1525967	golang.org/x/tools/internal/lsp/cache.(*importer).Import+0x87		/Users/muir/projects/tools/internal/lsp/cache/check.go:41
#	0x1387559	go/types.(*Checker).importPackage+0x6e9					/usr/local/go/src/go/types/resolver.go:161
#	0x1388d98	go/types.(*Checker).collectObjects+0x15f8				/usr/local/go/src/go/types/resolver.go:256
#	0x1367906	go/types.(*Checker).checkFiles+0x96					/usr/local/go/src/go/types/check.go:252
#	0x15269bb	go/types.(*Checker).Files+0x9db						/usr/local/go/src/go/types/check.go:245
#	0x15269aa	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0x9ca	/Users/muir/projects/tools/internal/lsp/cache/check.go:187
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f		/Users/muir/projects/tools/internal/lsp/cache/check.go:68

1 @ 0x1030c0f 0x10078aa 0x1007880 0x100756b 0x1525c69 0x1525968 0x138755a 0x1388d99 0x1367907 0x15269bc 0x15269ab 0x1525f40 0x152acd5 0x1529983 0x1529cac 0x152a2f4 0x14c85be 0x1517a38 0x1523677 0x105d841
#	0x1525c68	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x1a8			/Users/muir/projects/tools/internal/lsp/cache/check.go:59
#	0x1525967	golang.org/x/tools/internal/lsp/cache.(*importer).Import+0x87			/Users/muir/projects/tools/internal/lsp/cache/check.go:41
#	0x1387559	go/types.(*Checker).importPackage+0x6e9						/usr/local/go/src/go/types/resolver.go:161
#	0x1388d98	go/types.(*Checker).collectObjects+0x15f8					/usr/local/go/src/go/types/resolver.go:256
#	0x1367906	go/types.(*Checker).checkFiles+0x96						/usr/local/go/src/go/types/check.go:252
#	0x15269bb	go/types.(*Checker).Files+0x9db							/usr/local/go/src/go/types/check.go:245
#	0x15269aa	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0x9ca		/Users/muir/projects/tools/internal/lsp/cache/check.go:187
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f			/Users/muir/projects/tools/internal/lsp/cache/check.go:68
#	0x152acd4	golang.org/x/tools/internal/lsp/cache.(*view).loadParseTypecheck+0x1e4		/Users/muir/projects/tools/internal/lsp/cache/load.go:49
#	0x1529982	golang.org/x/tools/internal/lsp/cache.(*goFile).GetPackages+0x322		/Users/muir/projects/tools/internal/lsp/cache/gofile.go:112
#	0x1529cab	golang.org/x/tools/internal/lsp/cache.(*goFile).GetPackage+0x4b			/Users/muir/projects/tools/internal/lsp/cache/gofile.go:137
#	0x152a2f3	golang.org/x/tools/internal/lsp/cache.(*goFile).GetActiveReverseDeps+0x73	/Users/muir/projects/tools/internal/lsp/cache/gofile.go:198
#	0x14c85bd	golang.org/x/tools/internal/lsp/source.Diagnostics+0x2ad			/Users/muir/projects/tools/internal/lsp/source/diagnostics.go:88
#	0x1517a37	golang.org/x/tools/internal/lsp.(*Server).Diagnostics+0x267			/Users/muir/projects/tools/internal/lsp/diagnostics.go:27
#	0x1523676	golang.org/x/tools/internal/lsp.(*Server).didOpen.func1+0x66			/Users/muir/projects/tools/internal/lsp/text_synchronization.go:29

1 @ 0x1030c0f 0x102c3da 0x102b9c6 0x10bb88b 0x10bdeca 0x10bdeab 0x114bee2 0x1166b52 0x1165728 0x12e78fd 0x1512856 0x1512803 0x105d841
#	0x102b9c5	internal/poll.runtime_pollWait+0x55			/usr/local/go/src/runtime/netpoll.go:182
#	0x10bb88a	internal/poll.(*pollDesc).wait+0x9a			/usr/local/go/src/internal/poll/fd_poll_runtime.go:87
#	0x10bdec9	internal/poll.(*pollDesc).waitRead+0x1b9		/usr/local/go/src/internal/poll/fd_poll_runtime.go:92
#	0x10bdeaa	internal/poll.(*FD).Accept+0x19a			/usr/local/go/src/internal/poll/fd_unix.go:384
#	0x114bee1	net.(*netFD).accept+0x41				/usr/local/go/src/net/fd_unix.go:238
#	0x1166b51	net.(*TCPListener).accept+0x31				/usr/local/go/src/net/tcpsock_posix.go:139
#	0x1165727	net.(*TCPListener).Accept+0x47				/usr/local/go/src/net/tcpsock.go:260
#	0x12e78fc	net/http.(*Server).Serve+0x22c				/usr/local/go/src/net/http/server.go:2859
#	0x1512855	net/http.Serve+0x4c5					/usr/local/go/src/net/http/server.go:2456
#	0x1512802	golang.org/x/tools/internal/lsp/debug.Serve.func1+0x472	/Users/muir/projects/tools/internal/lsp/debug/serve.go:232

1 @ 0x1030c0f 0x1040f89 0x1040f5f 0x1040cfd 0x1073419 0x1528b22 0x1526dad 0x1525f40 0x1525968 0x138755a 0x1388d99 0x1367907 0x15269bc 0x15269ab 0x1525f40 0x1525968 0x138755a 0x1388d99 0x1367907 0x15269bc 0x15269ab 0x1525f40 0x105d841
#	0x1040cfc	sync.runtime_SemacquireMutex+0x3c					/usr/local/go/src/runtime/sema.go:71
#	0x1073418	sync.(*Mutex).Lock+0x108						/usr/local/go/src/sync/mutex.go:134
#	0x1528b21	golang.org/x/tools/internal/lsp/cache.(*fileBase).Handle+0x41		/Users/muir/projects/tools/internal/lsp/cache/file.go:60
#	0x1526dac	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0xdcc	/Users/muir/projects/tools/internal/lsp/cache/check.go:126
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f		/Users/muir/projects/tools/internal/lsp/cache/check.go:68
#	0x1525967	golang.org/x/tools/internal/lsp/cache.(*importer).Import+0x87		/Users/muir/projects/tools/internal/lsp/cache/check.go:41
#	0x1387559	go/types.(*Checker).importPackage+0x6e9					/usr/local/go/src/go/types/resolver.go:161
#	0x1388d98	go/types.(*Checker).collectObjects+0x15f8				/usr/local/go/src/go/types/resolver.go:256
#	0x1367906	go/types.(*Checker).checkFiles+0x96					/usr/local/go/src/go/types/check.go:252
#	0x15269bb	go/types.(*Checker).Files+0x9db						/usr/local/go/src/go/types/check.go:245
#	0x15269aa	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0x9ca	/Users/muir/projects/tools/internal/lsp/cache/check.go:187
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f		/Users/muir/projects/tools/internal/lsp/cache/check.go:68
#	0x1525967	golang.org/x/tools/internal/lsp/cache.(*importer).Import+0x87		/Users/muir/projects/tools/internal/lsp/cache/check.go:41
#	0x1387559	go/types.(*Checker).importPackage+0x6e9					/usr/local/go/src/go/types/resolver.go:161
#	0x1388d98	go/types.(*Checker).collectObjects+0x15f8				/usr/local/go/src/go/types/resolver.go:256
#	0x1367906	go/types.(*Checker).checkFiles+0x96					/usr/local/go/src/go/types/check.go:252
#	0x15269bb	go/types.(*Checker).Files+0x9db						/usr/local/go/src/go/types/check.go:245
#	0x15269aa	golang.org/x/tools/internal/lsp/cache.(*importer).typeCheck+0x9ca	/Users/muir/projects/tools/internal/lsp/cache/check.go:187
#	0x1525f3f	golang.org/x/tools/internal/lsp/cache.(*importer).getPkg+0x47f		/Users/muir/projects/tools/internal/lsp/cache/check.go:68

1 @ 0x1030c0f 0x1040f89 0x1040f5f 0x1040cfd 0x1073419 0x15296c4 0x1529cac 0x152a2f4 0x14c85be 0x1517a38 0x1523677 0x105d841
#	0x1040cfc	sync.runtime_SemacquireMutex+0x3c						/usr/local/go/src/runtime/sema.go:71
#	0x1073418	sync.(*Mutex).Lock+0x108							/usr/local/go/src/sync/mutex.go:134
#	0x15296c3	golang.org/x/tools/internal/lsp/cache.(*goFile).GetPackages+0x63		/Users/muir/projects/tools/internal/lsp/cache/gofile.go:108
#	0x1529cab	golang.org/x/tools/internal/lsp/cache.(*goFile).GetPackage+0x4b			/Users/muir/projects/tools/internal/lsp/cache/gofile.go:137
#	0x152a2f3	golang.org/x/tools/internal/lsp/cache.(*goFile).GetActiveReverseDeps+0x73	/Users/muir/projects/tools/internal/lsp/cache/gofile.go:198
#	0x14c85bd	golang.org/x/tools/internal/lsp/source.Diagnostics+0x2ad			/Users/muir/projects/tools/internal/lsp/source/diagnostics.go:88
#	0x1517a37	golang.org/x/tools/internal/lsp.(*Server).Diagnostics+0x267			/Users/muir/projects/tools/internal/lsp/diagnostics.go:27
#	0x1523676	golang.org/x/tools/internal/lsp.(*Server).didOpen.func1+0x66			/Users/muir/projects/tools/internal/lsp/text_synchronization.go:29

1 @ 0x1030c0f 0x1040f89 0x1040f5f 0x1040cfd 0x1073419 0x153371f 0x153615e 0x1535116 0x1535cd0 0x153158a 0x1530a2e 0x1521630 0x151ea39 0x13265c4 0x131ae07 0x105d841
#	0x1040cfc	sync.runtime_SemacquireMutex+0x3c					/usr/local/go/src/runtime/sema.go:71
#	0x1073418	sync.(*Mutex).Lock+0x108						/usr/local/go/src/sync/mutex.go:134
#	0x153371e	golang.org/x/tools/internal/lsp/cache.(*goFile).invalidateContent+0x7e	/Users/muir/projects/tools/internal/lsp/cache/view.go:231
#	0x153615d	golang.org/x/tools/internal/lsp/cache.(*view).getFile.func1+0x4d	/Users/muir/projects/tools/internal/lsp/cache/view.go:354
#	0x1535115	golang.org/x/tools/internal/lsp/cache.(*WatchMap).Notify+0xd5		/Users/muir/projects/tools/internal/lsp/cache/watcher.go:54
#	0x1535ccf	golang.org/x/tools/internal/lsp/cache.(*session).openOverlay.func1+0x6f	/Users/muir/projects/tools/internal/lsp/cache/session.go:267
#	0x1531589	golang.org/x/tools/internal/lsp/cache.(*session).openOverlay+0x389	/Users/muir/projects/tools/internal/lsp/cache/session.go:283
#	0x1530a2d	golang.org/x/tools/internal/lsp/cache.(*session).DidOpen+0xfd		/Users/muir/projects/tools/internal/lsp/cache/session.go:191
#	0x152162f	golang.org/x/tools/internal/lsp.(*Server).didOpen+0xcf			/Users/muir/projects/tools/internal/lsp/text_synchronization.go:23
#	0x151ea38	golang.org/x/tools/internal/lsp.(*Server).DidOpen+0x48			/Users/muir/projects/tools/internal/lsp/server.go:138
#	0x13265c3	golang.org/x/tools/internal/lsp/protocol.serverHandler.func1+0x20c3	/Users/muir/projects/tools/internal/lsp/protocol/tsserver.go:104
#	0x131ae06	golang.org/x/tools/internal/jsonrpc2.(*Conn).Run.func1+0x116		/Users/muir/projects/tools/internal/jsonrpc2/jsonrpc2.go:441

1 @ 0x104c81e 0x10a5637 0x10bc62f 0x10bc609 0x10c2020 0x10c1ff3 0x11cf69f 0x11d03ed 0x11d0890 0x13197d9 0x13197cb 0x1318c92 0x15426a1 0x154267b 0x1539f87 0x1538dd3 0x153c5bc 0x1539f87 0x1538dd3 0x154ba9a 0x103081c 0x105d841
#	0x104c81d	syscall.syscall+0x2d						/usr/local/go/src/runtime/sys_darwin.go:63
#	0x10a5636	syscall.read+0x66						/usr/local/go/src/syscall/zsyscall_darwin_amd64.go:1169
#	0x10bc62e	syscall.Read+0x12e						/usr/local/go/src/syscall/syscall_unix.go:172
#	0x10bc608	internal/poll.(*FD).Read+0x108					/usr/local/go/src/internal/poll/fd_unix.go:165
#	0x10c201f	os.(*File).read+0x6f						/usr/local/go/src/os/file_unix.go:263
#	0x10c1ff2	os.(*File).Read+0x42						/usr/local/go/src/os/file.go:108
#	0x11cf69e	bufio.(*Reader).fill+0x10e					/usr/local/go/src/bufio/bufio.go:100
#	0x11d03ec	bufio.(*Reader).ReadSlice+0x3c					/usr/local/go/src/bufio/bufio.go:356
#	0x11d088f	bufio.(*Reader).ReadBytes+0x6f					/usr/local/go/src/bufio/bufio.go:434
#	0x13197d8	bufio.(*Reader).ReadString+0x98					/usr/local/go/src/bufio/bufio.go:474
#	0x13197ca	golang.org/x/tools/internal/jsonrpc2.(*headerStream).Read+0x8a	/Users/muir/projects/tools/internal/jsonrpc2/stream.go:97
#	0x1318c91	golang.org/x/tools/internal/jsonrpc2.(*Conn).Run+0xa1		/Users/muir/projects/tools/internal/jsonrpc2/jsonrpc2.go:396
#	0x15426a0	golang.org/x/tools/internal/lsp.(*Server).Run+0x540		/Users/muir/projects/tools/internal/lsp/server.go:61
#	0x154267a	golang.org/x/tools/internal/lsp/cmd.(*Serve).Run+0x51a		/Users/muir/projects/tools/internal/lsp/cmd/serve.go:95
#	0x1539f86	golang.org/x/tools/internal/tool.Main.func2+0xb6		/Users/muir/projects/tools/internal/tool/tool.go:130
#	0x1538dd2	golang.org/x/tools/internal/tool.Main+0x242			/Users/muir/projects/tools/internal/tool/tool.go:131
#	0x153c5bb	golang.org/x/tools/internal/lsp/cmd.(*Application).Run+0x4ab	/Users/muir/projects/tools/internal/lsp/cmd/cmd.go:106
#	0x1539f86	golang.org/x/tools/internal/tool.Main.func2+0xb6		/Users/muir/projects/tools/internal/tool/tool.go:130
#	0x1538dd2	golang.org/x/tools/internal/tool.Main+0x242			/Users/muir/projects/tools/internal/tool/tool.go:131
#	0x154ba99	main.main+0x119							/Users/muir/projects/tools/cmd/gopls/main.go:22
#	0x103081b	runtime.main+0x20b						/usr/local/go/src/runtime/proc.go:200

1 @ 0x104c81e 0x10a5637 0x10bc62f 0x10bc609 0x114b5cf 0x115db39 0x12dd378 0x105d841
#	0x104c81d	syscall.syscall+0x2d				/usr/local/go/src/runtime/sys_darwin.go:63
#	0x10a5636	syscall.read+0x66				/usr/local/go/src/syscall/zsyscall_darwin_amd64.go:1169
#	0x10bc62e	syscall.Read+0x12e				/usr/local/go/src/syscall/syscall_unix.go:172
#	0x10bc608	internal/poll.(*FD).Read+0x108			/usr/local/go/src/internal/poll/fd_unix.go:165
#	0x114b5ce	net.(*netFD).Read+0x4e				/usr/local/go/src/net/fd_unix.go:202
#	0x115db38	net.(*conn).Read+0x68				/usr/local/go/src/net/net.go:177
#	0x12dd377	net/http.(*connReader).backgroundRead+0x57	/usr/local/go/src/net/http/server.go:677

1 @ 0x1505550 0x1505370 0x1501f40 0x150ece6 0x150f747 0x12e4244 0x12e6146 0x12e7518 0x12e3201 0x105d841
#	0x150554f	runtime/pprof.writeRuntimeProfile+0x8f	/usr/local/go/src/runtime/pprof/pprof.go:708
#	0x150536f	runtime/pprof.writeGoroutine+0x9f	/usr/local/go/src/runtime/pprof/pprof.go:670
#	0x1501f3f	runtime/pprof.(*Profile).WriteTo+0x38f	/usr/local/go/src/runtime/pprof/pprof.go:329
#	0x150ece5	net/http/pprof.handler.ServeHTTP+0x355	/usr/local/go/src/net/http/pprof/pprof.go:245
#	0x150f746	net/http/pprof.Index+0x6f6		/usr/local/go/src/net/http/pprof/pprof.go:268
#	0x12e4243	net/http.HandlerFunc.ServeHTTP+0x43	/usr/local/go/src/net/http/server.go:1995
#	0x12e6145	net/http.(*ServeMux).ServeHTTP+0x1d5	/usr/local/go/src/net/http/server.go:2375
#	0x12e7517	net/http.serverHandler.ServeHTTP+0xa7	/usr/local/go/src/net/http/server.go:2774
#	0x12e3200	net/http.(*conn).serve+0x850		/usr/local/go/src/net/http/server.go:1878

/cc @stamblerre

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgegoplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions