v0.5.6 — Fix Callback Stack-Move Corruption
What's Changed
Fixed — Critical: Callback Stack-Move Corruption
When a C callback re-enters Go and the callback's Go code grows the goroutine stack (copystack), syscallArgs on the goroutine stack would move — but syscallN running on g0 still held the old address. Return values were written to freed/recycled memory, causing silent data corruption.
Root cause: The v0.5.4 //go:noescape optimization kept syscallArgs on the goroutine stack. The Go runtime clears syscallsp during callback re-entry (cgocallbackg → exitsyscall()), allowing copystack to fire. See Go issues #8771, #11089.
Fix: syscallArgs is now heap-allocated via sync.Pool, immune to goroutine stack moves. Pool reuse gives 0 allocs/op in steady state. The //go:noescape directive has been removed from hot-path runtime_cgocall declarations.
Also in this release
- sret cleanup — simplified >16B struct return path, removed redundant
sretBuf TestCallbackGrowStack— deterministic reproducer for the stack-move bugTestStructReturn24B— end-to-end test for >16B struct return via sret
Thanks to @tie for discovering the bug, writing the reproducer, and contributing the fix!