From 9e9be09e9a4a4b8d53eca2e7859533fa5128fd41 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 22 Jul 2026 10:17:09 -0700 Subject: [PATCH] testing: avoid Goexit without unwind support Goexit cannot run deferred functions on architectures without panic unwinding. Query runtime.supportsRecover before calling it so unsupported targets report an error instead of leaving the test runner blocked forever. --- compiler/compiler.go | 2 +- src/testing/testing.go | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 9c1abb213..19410d49e 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -2216,7 +2216,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) if fn := instr.StaticCallee(); fn != nil { // Direct function call, either to a named or anonymous (directly // applied) function call. If it is anonymous, it may be a closure. - name := fn.RelString(nil) + name := b.getFunctionInfo(fn).linkName switch { case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm": return b.createInlineAsm(instr.Args) diff --git a/src/testing/testing.go b/src/testing/testing.go index 25b01b0fc..60d8fab64 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -25,6 +25,7 @@ import ( "time" "unicode" "unicode/utf8" + _ "unsafe" ) // Testing flags. @@ -215,7 +216,10 @@ func (c *common) Failed() bool { func (c *common) FailNow() { c.Fail() c.finished = true - runtime.Goexit() + if supportsRecover() { + runtime.Goexit() + } + c.Error("FailNow is incomplete, requires runtime.Goexit()") } // log generates the output. @@ -287,13 +291,19 @@ func (c *common) Skipf(format string, args ...any) { func (c *common) SkipNow() { c.skip() c.finished = true - runtime.Goexit() + if supportsRecover() { + runtime.Goexit() + } + c.Error("SkipNow is incomplete, requires runtime.Goexit()") } func (c *common) skip() { c.skipped = true } +//go:linkname supportsRecover runtime.supportsRecover +func supportsRecover() bool + // Skipped reports whether the test was skipped. func (c *common) Skipped() bool { return c.skipped