Description
What version of Go are you using (go version
)?
PS C:\Users\Lars Meyer\src\sys> go version go version go1.20.3 windows/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
PS C:\Users\Lars Meyer\src\sys> go env set GO111MODULE= set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\Lars Meyer\AppData\Local\go-build set GOENV=C:\Users\Lars Meyer\AppData\Roaming\go\env set GOEXE=.exe set GOEXPERIMENT= set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GOMODCACHE=C:\Program Files\Go\pkg\mod set GONOPROXY=code.enginsight.org set GONOSUMDB=code.enginsight.org set GOOS=windows set GOPATH=C:\Program Files\Go set GOPRIVATE=code.enginsight.org set GOPROXY=https://proxy.golang.org,direct set GOROOT=C:\Program Files\Go set GOSUMDB=sum.golang.org set GOTMPDIR= set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64 set GOVCS= set GOVERSION=go1.20.3 set GCCGO=gccgo set GOAMD64=v1 set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD=C:\Users\Lars Meyer\src\sys\go.mod set GOWORK= set CGO_CFLAGS=-O2 -g set CGO_CPPFLAGS= set CGO_CXXFLAGS=-O2 -g set CGO_FFLAGS=-O2 -g set CGO_LDFLAGS=-O2 -g set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 '-fdebug-prefix-map=C:\Users\Lars Meyer\AppData\Local\Temp\go-build2366456271=/tmp/go-build' -gno-record-gcc-switches
What did you do?
I am running the Windows service example.
I have forked the sys
repository and added svc.AcceptSessionChange
to the accepted service commands. (I have also redirected stderr
/stdout
to a file example.log
next to the executable to be able to catch the crash output.)
https://github.com/elmeyer/sys/tree/windows-svc-example-checkptr
What did you expect to see?
No errors when running the service example built with -race
.
What did you see instead?
When logging out and logging back in, a session change notification is triggered. The resulting call to svc.ctlHandler
receives a uintptr
to svc.theService
in the context
parameter. Its conversion back to a *svc.service
seems to be what triggers this crash.
example.log
fatal error: checkptr: pointer arithmetic result points to invalid allocationgoroutine 1 [running, locked to thread]:
runtime.throw({0x58bdc4?, 0x4aa139?})
C:/Program Files/Go/src/runtime/panic.go:1047 +0x65 fp=0xc00014b5d0 sp=0xc00014b5a0 pc=0x479305
runtime.checkptrArithmetic(0x0?, {0x0, 0x0, 0x41d750?})
C:/Program Files/Go/src/runtime/checkptr.go:69 +0xaa fp=0xc00014b600 sp=0xc00014b5d0 pc=0x44ac4a
golang.org/x/sys/windows/svc.ctlHandler(0xe, 0x6, 0x1614550, 0x6ca6c0)
C:/Users/Lars Meyer/src/sys/windows/svc/service.go:204 +0x4c fp=0xc00014b658 sp=0xc00014b600 pc=0x54f28c
runtime.call32(0x0, 0x58c580, 0xc00014b6f0, 0x0, 0x0, 0x20, 0xc00014b948)
C:/Program Files/Go/src/runtime/asm_amd64.s:729 +0x4e fp=0xc00014b688 sp=0xc00014b658 pc=0x4a6cae
runtime.callbackWrap(0x146fab0)
C:/Program Files/Go/src/runtime/syscall_windows.go:396 +0x1ef fp=0xc00014ba68 sp=0xc00014b688 pc=0x496fef
runtime.cgocallbackg1(0x496e00, 0x4513c7?, 0x0)
C:/Program Files/Go/src/runtime/cgocall.go:315 +0x2c5 fp=0xc00014bb30 sp=0xc00014ba68 pc=0x4481c5
runtime.cgocallbackg(0xc000042000?, 0x300000002?, 0xc000042000?)
C:/Program Files/Go/src/runtime/cgocall.go:234 +0x105 fp=0xc00014bbc0 sp=0xc00014bb30 pc=0x447e25
runtime.cgocallbackg(0x496e00, 0x146fab0, 0x0)
:1 +0x34 fp=0xc00014bbe8 sp=0xc00014bbc0 pc=0x4ab414
runtime.cgocallback(0x447c99, 0x4aa9a0, 0x6cb140)
C:/Program Files/Go/src/runtime/asm_amd64.s:998 +0xcf fp=0xc00014bc10 sp=0xc00014bbe8 pc=0x4a876f
runtime.systemstack_switch()
C:/Program Files/Go/src/runtime/asm_amd64.s:463 fp=0xc00014bc18 sp=0xc00014bc10 pc=0x4a66c0
runtime.cgocall(0x4aa9a0, 0x6cb140)
C:/Program Files/Go/src/runtime/cgocall.go:167 +0xb9 fp=0xc00014bc50 sp=0xc00014bc18 pc=0x447c99
syscall.SyscallN(0x7ffa72487cd0?, {0xc00014bce8?, 0x3?, 0x0?})
C:/Program Files/Go/src/runtime/syscall_windows.go:557 +0x109 fp=0xc00014bcc8 sp=0xc00014bc50 pc=0x4a5509
syscall.Syscall(0xc00013fce0?, 0xc000108120?, 0xc0001401e0?, 0xc0001401e0?, 0x54fe18?)
C:/Program Files/Go/src/runtime/syscall_windows.go:495 +0x3b fp=0xc00014bd10 sp=0xc00014bcc8 pc=0x4a51db
golang.org/x/sys/windows.StartServiceCtrlDispatcher(0xc00014bda8)
C:/Users/Lars Meyer/src/sys/windows/zsyscall_windows.go:1331 +0xa5 fp=0xc00014bd80 sp=0xc00014bd10 pc=0x526d25
golang.org/x/sys/windows/svc.Run({0x580b70, 0x9}, {0x605b98?, 0x71d810})
C:/Users/Lars Meyer/src/sys/windows/svc/service.go:301 +0x176 fp=0xc00014bdd8 sp=0xc00014bd80 pc=0x54fe56
main.runService({0x580b70, 0x9}, 0x0)
C:/Users/Lars Meyer/src/sys/windows/svc/example/service.go:90 +0x2e9 fp=0xc00014bed0 sp=0xc00014bdd8 pc=0x558169
main.main()
C:/Users/Lars Meyer/src/sys/windows/svc/example/main.go:86 +0x40d fp=0xc00014bf80 sp=0xc00014bed0 pc=0x556c0d
runtime.main()
C:/Program Files/Go/src/runtime/proc.go:250 +0x1f7 fp=0xc00014bfe0 sp=0xc00014bf80 pc=0x47ba77
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00014bfe8 sp=0xc00014bfe0 pc=0x4a89c1goroutine 17 [select, locked to thread]:
runtime.gopark(0xc0001119e8?, 0x4?, 0x0?, 0xc0?, 0xc0001117d4?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc0001115e8 sp=0xc0001115c8 pc=0x47be96
runtime.selectgo(0xc0001119e8, 0xc0001117cc, 0xc000111790?, 0x1, 0x0?, 0x1)
C:/Program Files/Go/src/runtime/select.go:327 +0x8be fp=0xc000111748 sp=0xc0001115e8 pc=0x48b9fe
golang.org/x/sys/windows/svc.serviceMain(0x3, 0x161ace8)
C:/Users/Lars Meyer/src/sys/windows/svc/service.go:253 +0x676 fp=0xc000111a38 sp=0xc000111748 pc=0x54f9d6
runtime.call16(0x0, 0x58c590, 0xc000111ac0, 0x0, 0x0, 0x10, 0xc000111d18)
C:/Program Files/Go/src/runtime/asm_amd64.s:728 +0x4e fp=0xc000111a58 sp=0xc000111a38 pc=0x4a6c0e
runtime.callbackWrap(0x28c5fdf0)
C:/Program Files/Go/src/runtime/syscall_windows.go:396 +0x1ef fp=0xc000111e38 sp=0xc000111a58 pc=0x496fef
runtime.cgocallbackg1(0x496e00, 0x0?, 0x0)
C:/Program Files/Go/src/runtime/cgocall.go:315 +0x2c5 fp=0xc000111f00 sp=0xc000111e38 pc=0x4481c5
runtime.cgocallbackg(0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/cgocall.go:234 +0x105 fp=0xc000111f90 sp=0xc000111f00 pc=0x447e25
runtime.cgocallbackg(0x496e00, 0x28c5fdf0, 0x0)
:1 +0x34 fp=0xc000111fb8 sp=0xc000111f90 pc=0x4ab414
runtime.cgocallback(0x0, 0x0, 0x0)
C:/Program Files/Go/src/runtime/asm_amd64.s:998 +0xcf fp=0xc000111fe0 sp=0xc000111fb8 pc=0x4a876f
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000111fe8 sp=0xc000111fe0 pc=0x4a89c1goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc000045fb0 sp=0xc000045f90 pc=0x47be96
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:387
runtime.forcegchelper()
C:/Program Files/Go/src/runtime/proc.go:305 +0xb2 fp=0xc000045fe0 sp=0xc000045fb0 pc=0x47bcb2
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000045fe8 sp=0xc000045fe0 pc=0x4a89c1
created by runtime.init.6
C:/Program Files/Go/src/runtime/proc.go:293 +0x25goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc000047f80 sp=0xc000047f60 pc=0x47be96
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:387
runtime.bgsweep(0x0?)
C:/Program Files/Go/src/runtime/mgcsweep.go:278 +0x8e fp=0xc000047fc8 sp=0xc000047f80 pc=0x466a4e
runtime.gcenable.func1()
C:/Program Files/Go/src/runtime/mgc.go:178 +0x26 fp=0xc000047fe0 sp=0xc000047fc8 pc=0x45bec6
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000047fe8 sp=0xc000047fe0 pc=0x4a89c1
created by runtime.gcenable
C:/Program Files/Go/src/runtime/mgc.go:178 +0x6bgoroutine 4 [GC scavenge wait]:
runtime.gopark(0xc00001a070?, 0x6044b8?, 0x1?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc000057f70 sp=0xc000057f50 pc=0x47be96
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:387
runtime.(*scavengerState).park(0x6ca800)
C:/Program Files/Go/src/runtime/mgcscavenge.go:400 +0x53 fp=0xc000057fa0 sp=0xc000057f70 pc=0x4649b3
runtime.bgscavenge(0x0?)
C:/Program Files/Go/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000057fc8 sp=0xc000057fa0 pc=0x464f65
runtime.gcenable.func2()
C:/Program Files/Go/src/runtime/mgc.go:179 +0x26 fp=0xc000057fe0 sp=0xc000057fc8 pc=0x45be66
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000057fe8 sp=0xc000057fe0 pc=0x4a89c1
created by runtime.gcenable
C:/Program Files/Go/src/runtime/mgc.go:179 +0xaagoroutine 18 [finalizer wait]:
runtime.gopark(0x6cae80?, 0x6ab7d0?, 0x0?, 0x0?, 0xc000049f70?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc000049e28 sp=0xc000049e08 pc=0x47be96
runtime.runfinq()
C:/Program Files/Go/src/runtime/mfinal.go:193 +0x147 fp=0xc000049fe0 sp=0xc000049e28 pc=0x45af27
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000049fe8 sp=0xc000049fe0 pc=0x4a89c1
created by runtime.createfing
C:/Program Files/Go/src/runtime/mfinal.go:163 +0x45goroutine 5 [select]:
runtime.gopark(0xc00004bf38?, 0x2?, 0x40?, 0x30?, 0xc00004be44?)
C:/Program Files/Go/src/runtime/proc.go:381 +0xd6 fp=0xc00004bca0 sp=0xc00004bc80 pc=0x47be96
runtime.selectgo(0xc00004bf38, 0xc00004be40, 0x57fefe?, 0x0, 0x2?, 0x1)
C:/Program Files/Go/src/runtime/select.go:327 +0x8be fp=0xc00004be00 sp=0xc00004bca0 pc=0x48b9fe
main.(*myservice).Execute(0xc00004c000?, {0xc00001c030, 0x3, 0x3}, 0xc00005c000, 0x0?)
C:/Users/Lars Meyer/src/sys/windows/svc/example/service.go:33 +0x193 fp=0xc00004bf68 sp=0xc00004be00 pc=0x557a53
golang.org/x/sys/windows/svc.serviceMain.func2()
C:/Users/Lars Meyer/src/sys/windows/svc/service.go:241 +0x95 fp=0xc00004bfe0 sp=0xc00004bf68 pc=0x54fc95
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004bfe8 sp=0xc00004bfe0 pc=0x4a89c1
created by golang.org/x/sys/windows/svc.serviceMain
C:/Users/Lars Meyer/src/sys/windows/svc/service.go:240 +0x4d6
I fundamentally don't understand why a pointer to svc.theService
is being passed to windows.RegisterServiceCtrlHandlerEx
. The comment for svc.theService
explicitly states:
var theService service // This is, unfortunately, a global, which means only one service per process.
while the documentation for RegisterServiceCtrlHandlerExW
states:
[in, optional] lpContext
Any user-defined data. This parameter, which is passed to the handler function, can help identify the service when multiple services share a process.
(emphasis mine)
The crash naturally disappears when this parameter is replaced with 0 and svc.ctlHandler
is modified to assume that all calls to it refer to svc.theService
. However, the root cause of this checkptr
failure remains unclear.
cc @ericrange who helped reproduce this problem.