-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
Go version
go version go1.25.5 windows/amd64
go version go1.24.4 windows/amd64
(others untested)
Output of go env in your module/workspace:
set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=1
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\Matt Hall\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\Matt Hall\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\MATTHA~1\AppData\Local\Temp\go-build4154539945=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=C:\Users\Matt Hall\Documents\test\go.mod
set GOMODCACHE=C:\Users\Matt Hall\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\Matt Hall\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=local
set GOTELEMETRYDIR=C:\Users\Matt Hall\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.25.5
set GOWORK=
set PKG_CONFIG=pkg-configWhat did you do?
Ran the following program
package main
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"golang.org/x/sys/windows"
)
type SignalHandler struct {
wg sync.WaitGroup
cancel context.CancelFunc
}
func (s *SignalHandler) Start() {
ctx, cancel := context.WithCancel(context.Background())
s.cancel = cancel
s.wg.Add(1)
go s.handle(ctx)
}
func (s *SignalHandler) Stop() {
s.cancel()
s.wg.Wait()
}
func (s *SignalHandler) handle(ctx context.Context) {
defer s.wg.Done()
ch := make(chan os.Signal, 1)
// 0xaa is some nonsense signal. windows.SIGTERM etc work just as well.
// Anything but os.Interrupt
signal.Notify(ch, windows.Signal(0xaa))
defer signal.Stop(ch)
for {
select {
case <-ctx.Done():
return
case <-ch:
continue
}
}
}
func main() {
h := &SignalHandler{}
fmt.Println("start")
h.Start()
fmt.Println("stop")
h.Stop()
}What did you see happen?
"start" and "stop" are both printed but the process then hangs. The issue is signal.Stop:
0 0x00007ff7a4b83694 in runtime.mcall
at C:/Program Files/Go/src/runtime/asm_amd64.s:457
1 0x00007ff7a4b7f9f6 in runtime.Gosched
at C:/Program Files/Go/src/runtime/proc.go:389
2 0x00007ff7a4b7f9f6 in os/signal.signalWaitUntilIdle
at C:/Program Files/Go/src/runtime/sigqueue.go:193
3 0x00007ff7a4bbf4aa in os/signal.Stop
at C:/Program Files/Go/src/os/signal/signal.go:215
4 0x00007ff7a4bca1e5 in main.(*SignalHandler).handle.deferwrap2
at C:/Users/Matt Hall/Documents/test/main.go:36
5 0x00007ff7a4bca157 in main.(*SignalHandler).handle
at C:/Users/Matt Hall/Documents/test/main.go:42
6 0x00007ff7a4bc9fa8 in main.(*SignalHandler).Start.gowrap1
at C:/Users/Matt Hall/Documents/test/main.go:23
7 0x00007ff7a4b856e1 in runtime.goexit
at C:/Program Files/Go/src/runtime/asm_amd64.s:1693
Digging around a bit more sig.state is stuck in idle. I believe this is because idle is the zero value and sigsend/signal_recv - which advance the state - are never run.
If I pass os.Interrupt to signal.Notify instead signal_recv is called and the process exists. I can't find where signal_recv is called. The backtrace ends in assembly which looks suspicious:
0 0x00007ff76581e94e in os/signal.signal_recv
at C:/Program Files/Go/src/runtime/sigqueue.go:130
1 0x00007ff76585e9d3 in os/signal.loop
at C:/Program Files/Go/src/os/signal/signal_unix.go:23
2 0x00007ff765824741 in runtime.goexit
at C:/Program Files/Go/src/runtime/asm_amd64.s:1693
What did you expect to see?
The process should terminate.
I think the docs could also be clearer here. Reading between the lines it appears the only valid value to be passed on Windows is os.Interrupted, but this is not stated outright.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status