Repository navigation
Description
Go version
go version go1.25.7 darwin/arm64
Output of go env in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/ukai/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/ukai/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/fg/y90rmtzj3hz3hqtpwn0qwzmc000p7r/T/go-build960639305=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/ukai/src/crbuild/build/siso/go.mod'
GOMODCACHE='/Users/ukai/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/ukai/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/ukai/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.25.7'
GOWORK=''
PKG_CONFIG='pkg-config'What did you do?
go binary (without cgo) runs with profilers
$ go version -m third_party/siso/cipd/siso
...
build -buildmode=exe
build -compiler=gc
build -trimpath=true
build CGO_ENABLED=0
build GOARCH=arm64
build GOOS=darwin
build GOARM64=v8.0
https://ci.chromium.org/ui/p/chromium/builders/build/ios-build-perf-developer/7889/overview
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8691654715001248849/+/u/Clean_builds/Build_chrome_without_remote_cache_with_Siso_in_native_mode/stdout
https://ci.chromium.org/ui/p/chromium/builders/build/ios-build-perf-siso/25669/overview
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8690003051682517681/+/u/Clean_builds/Build_all_with_remote_cache/stdout
What did you see happen?
signal 27 received on thread with no signal stack
fatal error: non-Go code disabled sigaltstack
runtime stack:
runtime.throw({0x10304c6af?, 0x0?})
runtime/panic.go:1094 +0x34 fp=0x42ec56860 sp=0x42ec56830 pc=0x10219ebe4
runtime.noSignalStack(...)
runtime/signal_unix.go:1106
runtime.adjustSignalStack2(0x1b, 0x42ec56918, 0x140797ed008, 0x1)
runtime/signal_unix.go:599 +0xa0 fp=0x42ec56890 sp=0x42ec56860 pc=0x102180500
runtime.adjustSignalStack(0x1b, 0x140797ed008, 0x42ec56940)
runtime/signal_unix.go:588 +0x230 fp=0x42ec56910 sp=0x42ec56890 pc=0x102180450
runtime.sigtrampgo(0x1b, 0x42ec56ab0, 0x42ec56b18)
runtime/signal_unix.go:480 +0x84 fp=0x42ec56990 sp=0x42ec56910 pc=0x10217ff94
runtime.sigtrampgo(0x1b, 0x42ec56ab0, 0x42ec56b18)
<autogenerated>:1 +0x1c fp=0x42ec569c0 sp=0x42ec56990 pc=0x1021a9d0c
runtime.sigtramp()
runtime/sys_darwin_arm64.s:227 +0x4c fp=0x42ec56a80 sp=0x42ec569c0 pc=0x1021a884c
goroutine 17 gp=0x14000002700 m=1 mp=0x140000a8008 [syscall, locked to thread]:
runtime.goexit({})
runtime/asm_arm64.s:1268 +0x4 fp=0x140000b6fe0 sp=0x140000b6fe0 pc=0x1021a7824
What did you expect to see?
no panic
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
gabyhelp commentedon Feb 13, 2026
Related Issues
Related Code Changes
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
JunyangShao commentedon Feb 13, 2026
@golang/runtime
ianlancetaylor commentedon Feb 13, 2026
The runtime error message is trying to tell you the problem: "fatal error: non-Go code disabled sigaltstack".
Quoting https://pkg.go.dev/os/signal:
In this case the signal is
SIGPROF. Look for non-Go code linked into your program that is setting up a signal handler forSIGPROF.ukai commentedon Feb 13, 2026
No non-Go code linked into the program, as
build CGO_ENABLED=0.I think
SIGPROFis used byruntime/pprofianlancetaylor commentedon Feb 13, 2026
Yes, runtime/pprof uses
SIGPROF.If there is no non-Go code involved in this program, then this should be impossible. The Go runtime always installs signal handlers with
SA_ONSTACKset. Is this problem reproducible? Is there a way that we can reproduce it ourselves?ukai commentedon Feb 13, 2026
It happened several times.
https://ci.chromium.org/ui/p/chromium/builders/build/ios-build-perf-developer/7889/overview
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8691654715001248849/+/u/Clean_builds/Build_chrome_without_remote_cache_with_Siso_in_native_mode/stdout
https://ci.chromium.org/ui/p/chromium/builders/build/ios-build-perf-siso/25663/overview
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8690040953658448481/+/u/Clean_builds/Build_all_without_remote_cache_with_Siso_disabling_clang_modules/stdout
https://ci.chromium.org/ui/p/chromium/builders/build/ios-build-perf-siso/25669/overview
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8690003051682517681/+/u/Clean_builds/Build_all_with_remote_cache/stdout
but no idea how to reproduce this yet.
happened rarely when
pprof.StartCPUProfileis called?suspect
github.com/ebitengine/purego?prattmic commentedon Feb 13, 2026
The purpose of purego is to call non-Go code (in an unsafe manner unsupported by the Go toolchain), so the libraries used from there would be my top suspects.
cherrymui commentedon Feb 25, 2026
For now we suspect the issue is the C library that this program uses clears the SA_ONSTACK. Could you check if that is the case? Thanks.
gopherbot commentedon Mar 25, 2026
Timed out in state WaitingForInfo. Closing.
(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)
ukai commentedon Jun 25, 2026
I would like to reopen this issue as we have performed a deep dive analysis and identified the exact root cause, proving that this is indeed a Go runtime race condition and not caused by external C libraries (the crash still occurs with
CGO_ENABLED=0).The issue is a race condition in dropm/mexit during thread teardown when SIGPROF is active.
Here is the detailed analysis
Description
We are observing intermittent crashes in a high-concurrency Go application (
sisobuild tool) running on macOS builders with CPU profiling enabled. The crash presents with the following fatal error:Signal 27 is
SIGPROF. The goroutine status at the time of the crash (visible in fuller logs) is often[syscall, locked to thread]with the stack top atruntime.goexit, indicating a thread teardown path.Root Cause Analysis
There is a race condition in
runtime.dropmandruntime.mexitduring thread de-initialization.1. The Race Window
In
src/runtime/proc.go,runtime.dropmperforms the following teardown:sigblock(false)blocks signals.unminit()callsunminitSignals()(on Darwin), which disables the alternate signal stack viasigaltstack(settingss_flags = _SS_DISABLE).setg(nil)clears thegpointer.A critical race window exists between
unminit()(disablingsigaltstack) andsetg(nil)(clearingg).2.
SIGPROFis UnblockableIn
src/runtime/signal_darwin.go,SIGPROFis defined as:Because it has the
_SigUnblockflag, it is not blocked during normal Go execution. More importantly, even thoughsigblockattempts to block all signals viapthread_sigmaskusingsigset_all(which has all bits set), on macOS,pthread_sigmaskmay not immediately prevent delivery of aSIGPROFthat is already pending or in flight in the kernel. It can still be delivered when transitioning through syscalls (like thesigaltstackcall insideunminit).3. Failure Mode
If
SIGPROFarrives afterunminit()has disabledsigaltstack, but beforesetg(nil)has clearedg:SIGPROFto the thread.sigaltstackis disabled, the signal handler (runtime.sigtramp) runs on the normal thread stack.sigtrampcallsruntime.load_g, which returns the still-validg(sincesetg(nil)hasn't run yet).sigtrampgois called withgp != nil.sigtrampgocallsruntime.adjustSignalStack.adjustSignalStackqueries the signal stack, sees it is disabled (_SS_DISABLE), and sincegp != nil, it assumes non-Go code disabled it and throws:fatal error: non-Go code disabled sigaltstackThis race is highly reproducible under heavy load with CPU profiling enabled, especially when threads are frequently entering/exiting Go (cgo transitions) or exiting (locked goroutines exiting).
WDYT? @ianlancetaylor @cherrymui
randall77 commentedon Jun 25, 2026
We're going to need some way to reproduce this to make any progress.
Does that mean you have a reproducer?
You say it reproduces with
CGO_ENABLED=0, but then say there are a lot of cgo transitions. I don't see how both can be true.Do you have a reference for this? That sounds like a kernel bug to me. On return from sigblock, the kernel should not deliver signals of any sort, "pending or in flight" notwithstanding.
ukai commentedon Jun 26, 2026
no, since race windows would be small, so happens one a month in our CI.
Ah, siso is built with CGO_ENABLED=0. cgo transitions are irrelevant here, I think.
Our guess is that
randall77 commentedon Jun 26, 2026
I don't see how that is possible without violating what
sigblockis supposed to do.The signal handler should never see
global == true. Even if the signal is async, and the kernel was preparing to deliver the async signal to this thread. It must either deliver the signal during the call tosigblock, or retry and deliver it to some other thread. It cannot deliver that signal aftersigblockreturns.If it is true that Darwin violates this, make a C reproducer and submit it to Apple.
ukai commentedon Oct 15, 2026
suspect ebitengine/purego#552
ukai commentedon Oct 26, 2026
seems https://github.com/ebitengine/purego/releases/tag/v0.11.2 fixed this issue.