Skip to content

x/tools/gopls: SEGV due to invalid g in brand new goroutine #76693

@adonovan

Description

@adonovan
#!stacks
"crash/crash" && "cache.(*parseCache).gc:+0"

Issue created by stacks.

Well this is an interesting one: we have a brand new goroutine that has executed one stack check and one preemption check, and yet its its R28 (g) is corrupt by the time of the second stack check.

TEXT golang.org/x/tools/gopls/internal/cache.(*parseCache).gc(SB) golang.org/x/tools/gopls@v0.20.0/internal/cache/parse_cache.go
  parse_cache.go:256    0x10081fbe0             f9400b90                MOVD 16(R28), R16                 <--- SEGV
...

TEXT golang.org/x/tools/gopls/internal/cache.newParseCache.gowrap1(SB) golang.org/x/tools/gopls@v0.20.0/internal/cache/parse_cache.go
  parse_cache.go:119    0x10081ef30             f9400b90                MOVD 16(R28), R16          // load g.stackguard0                                             
  parse_cache.go:119    0x10081ef34             eb3063ff                CMP R16, RSP                     // check overflow
  parse_cache.go:119    0x10081ef38             54000169                BLS 11(PC)                         // handle it                        
stackok:
  parse_cache.go:119    0x10081ef3c             f81e0ffe                MOVD.W R30, -32(RSP)        // save LR (R30)
  parse_cache.go:119    0x10081ef40             f81f83fd                MOVD R29, -8(RSP)              // save FP (R29)                                         
  parse_cache.go:119    0x10081ef44             d10023fd                SUB $8, RSP, R29                // displace the stack                                        
  parse_cache.go:119    0x10081ef48             f9401390                MOVD 32(R28), R16           //  load g._panic                                      
  parse_cache.go:119    0x10081ef4c             b5000130                CBNZ R16, 9(PC)                //  handle it   
nopanic:                                      
  parse_cache.go:119    0x10081ef50             f9400740                MOVD 8(R26), R0               // load c                                          
  parse_cache.go:119    0x10081ef54             94000323                CALL golang.org/x/tools/gopls/internal/cache.(*parseCache).gc(SB)       
  parse_cache.go:119    0x10081ef58             f85f83fd                MOVD -8(RSP), R29                <---- PC+1 is here                                       
...

This means something has corrupted R28 between the two stack checks. The only code that has run in this thread are the checks themselves. I think this implies only one of three possibilities:

  1. the runtime stack check corrupted R28.
  2. async preemption corrupted R28.
  3. hardware fault (unlikely: this class of crash is too common across our fleet of 8000 telemetry-enabled machines).

Of course, both of 1 and 2 could be explained by corruption of runtime internal data structures by an errant mutator, but I think we can safely conclude that the runtime must be involved in this corruption.

This stack 6__P9g was reported by telemetry:

golang.org/x/tools/gopls@v0.20.0 go1.25.4 darwin/arm64 gopls.client=vscode (2)

Use this command to reproduce the executable:
(HOME=$(mktemp -d); GOOS=darwin GOARCH=arm64 GOTOOLCHAIN=go1.25.4 go install golang.org/x/tools/gopls@v0.20.0 && find $HOME/go/bin -type f)
To disassemble: go tool objdump exe | less

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.compiler/runtimeIssues related to the Go compiler and/or runtime.goplsIssues related to the Go language server, gopls.gopls/telemetry-wins

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions