Repository navigation
internal/fakecgo: use per-OS values for pthread_sigmask how - #553
Merged
hajimehoshi merged 1 commit intoOct 15, 2026
Merged
Conversation
SIG_BLOCK, SIG_UNBLOCK and SIG_SETMASK were defined once with the Linux values 0, 1 and 2. Darwin, FreeBSD and NetBSD use 1, 2 and 3, so pthread_sigmask(SIG_SETMASK, ...) in _cgo_sys_thread_start ran as SIG_UNBLOCK there. Instead of blocking all signals across pthread_create, it unblocked them, and the new thread started with signals unblocked. A SIGPROF delivered after threadentry installed g0 but before mstart set the g0 stack bounds then crashed the runtime with "signal 27 received on thread with no signal stack". Define the constants in the per-OS files with each OS's values. Closes ebitengine#552 Co-Authored-By: Claude Opus 5.5 <[email protected]>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused constant correction preserves existing callers and platform selection, with no unresolved findings.
0 open findings
What changed in this PR
Fixes #552 by using OS-specific signal-mask constants in fakecgo, preventing incorrect signal handling during thread creation on Darwin and BSD.
Changes:
- Moves signal-mask constants from shared code into per-OS files.
- Corrects Darwin, FreeBSD, and NetBSD values while preserving Linux values.
- Adds source-header references.
| File | Description |
|---|---|
| internal/fakecgo/libcgo.go | Removes shared Linux-specific constants. |
| internal/fakecgo/libcgo_netbsd.go | Defines correct NetBSD values. |
| internal/fakecgo/libcgo_linux.go | Preserves Linux values locally. |
| internal/fakecgo/libcgo_freebsd.go | Defines correct FreeBSD values. |
| internal/fakecgo/libcgo_darwin.go | Defines correct Darwin values. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Member
Author
|
@TotallyGamerJet PTAL |
hajimehoshi
added a commit
that referenced
this pull request
Oct 15, 2026
SIG_BLOCK, SIG_UNBLOCK and SIG_SETMASK were defined once with the Linux values 0, 1 and 2. Darwin, FreeBSD and NetBSD use 1, 2 and 3, so pthread_sigmask(SIG_SETMASK, ...) in _cgo_sys_thread_start ran as SIG_UNBLOCK there. Instead of blocking all signals across pthread_create, it unblocked them, and the new thread started with signals unblocked. A SIGPROF delivered after threadentry installed g0 but before mstart set the g0 stack bounds then crashed the runtime with "signal 27 received on thread with no signal stack". Define the constants in the per-OS files with each OS's values. Closes #552 Co-authored-by: Claude Opus 5.5 <[email protected]>
kolkov
added a commit
to go-webgpu/goffi
that referenced
this pull request
Oct 15, 2026
SIG_BLOCK, SIG_UNBLOCK and SIG_SETMASK were defined once in libcgo.go
with the Linux values 0/1/2. Darwin, FreeBSD and NetBSD use 1/2/3, so
pthread_sigmask(SIG_SETMASK, ...) in _cgo_sys_thread_start ran as
SIG_UNBLOCK there: new runtime threads started with every signal
unblocked instead of blocked, and the restore call unblocked the saved
mask instead of reinstating it. A signal arriving before the new thread
had its g0 stack set up could crash the process.
Define the constants in libcgo_{darwin,freebsd,linux,netbsd}.go with
each system's values. Linux and Android were not affected.
Add TestSighowMatchesSystemHeaders, which compiles a probe with the
system C compiler and checks the constants against the host's
<signal.h>, so CI on macOS catches a mismatch.
Ported from ebitengine/purego#553 (ebitengine/purego#552).
kolkov
added a commit
to go-webgpu/goffi
that referenced
this pull request
Oct 15, 2026
SIG_BLOCK, SIG_UNBLOCK and SIG_SETMASK were defined once in libcgo.go
with the Linux values 0/1/2. Darwin, FreeBSD and NetBSD use 1/2/3, so
pthread_sigmask(SIG_SETMASK, ...) in _cgo_sys_thread_start ran as
SIG_UNBLOCK there: new runtime threads started with every signal
unblocked instead of blocked, and the restore call unblocked the saved
mask instead of reinstating it. A signal arriving before the new thread
had its g0 stack set up could crash the process.
Define the constants in libcgo_{darwin,freebsd,linux,netbsd}.go with
each system's values. Linux and Android were not affected.
Add TestSighowMatchesSystemHeaders, which compiles a probe with the
system C compiler and checks the constants against the host's
<signal.h>, so CI on macOS catches a mismatch.
Ported from ebitengine/purego#553 (ebitengine/purego#552).
kolkov
added a commit
to go-webgpu/goffi
that referenced
this pull request
Oct 15, 2026
SIG_BLOCK, SIG_UNBLOCK and SIG_SETMASK were defined once in libcgo.go
with the Linux values 0/1/2. Darwin, FreeBSD and NetBSD use 1/2/3, so
pthread_sigmask(SIG_SETMASK, ...) in _cgo_sys_thread_start ran as
SIG_UNBLOCK there: new runtime threads started with every signal
unblocked instead of blocked, and the restore call unblocked the saved
mask instead of reinstating it. A signal arriving before the new thread
had its g0 stack set up could crash the process.
Define the constants in libcgo_{darwin,freebsd,linux,netbsd}.go with
each system's values. Linux and Android were not affected.
Add TestSighowMatchesSystemHeaders, which compiles a probe with the
system C compiler and checks the constants against the host's
<signal.h>, so CI on macOS catches a mismatch.
Ported from ebitengine/purego#553 (ebitengine/purego#552).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What issue is this addressing?
Closes #552
What type of issue is this addressing?
bug
What this PR does | solves
SIG_BLOCK,SIG_UNBLOCKandSIG_SETMASKwere defined once ininternal/fakecgo/libcgo.gowith the Linux values 0, 1 and 2. Darwin, FreeBSD and NetBSD use 1, 2 and 3, sopthread_sigmask(SIG_SETMASK, ...)in_cgo_sys_thread_startran asSIG_UNBLOCKthere. Instead of blocking all signals acrosspthread_create, it unblocked them, and the new thread started with signals unblocked. A SIGPROF that arrived afterthreadentryinstalled g0, but beforemstartset the g0 stack bounds, crashed the runtime withsignal 27 received on thread with no signal stack(golang/go#77588).This PR moves the constants into the per-OS
libcgo_*.gofiles and gives each OS its own values, with a link to the header they come from. The values match the Go runtime's own definitions (os_darwin.go,os2_freebsd.go,os_netbsd.go,os_linux_generic.go).Testing
CGO_ENABLED=0: a program runs CPU profiling atruntime.SetCPUProfileRate(100000)while goroutines callruntime.LockOSThreadand exit without unlocking, so threads are constantly created and destroyed. Before this change, 9 of 13 ten-second runs crashed with the error above. With it, 0 of 10 crashed.go test ./...passes on darwin/arm64 withCGO_ENABLED=0andCGO_ENABLED=1.-gcflags=github.com/ebitengine/purego/internal/fakecgo=-std), netbsd and all supported linux architectures.Filed by Claude (Claude Code), on behalf of @hajimehoshi.
🤖 Generated with Claude Code