//go:norace doesn't effect ABI0 wrapper

108 views
Skip to first unread message

Jarrett Kuklis

unread,
Nov 30, 2022, 11:30:38 AM11/30/22
to golang-nuts
I am one of the main contributors to ebitengine/purego a library that aims to call into C code without invoking the C compiler. The main platform of support is darwin on arm64 and amd64. It uses //cgo_import_dynamic comments to get the symbols and calls them using runtime.cgocall.

That runtime function requires that runtime/cgo be imported which requires C. I used the work of notti/nocgo as inspiration to write an implementation of runtime/cgo entirely in Go (located at internal/fakecgo). It has worked for the ebitengine project really well. 

However, I was looking at the draft Go 1.20 release notes and saw that -race no longer requires Cgo to work on macOS. Which I am all for and really excited about! This means though that when -race and CGO_ENABLED=0 our faked runtime/cgo package has race code placed in it. From what I can tell this is bad because the code in this package is faking being C so it shouldn't call into the race detector. And it will SIGSEGV jumping to any code that tries to call it since the runtime isn't fully initialized by the time these functions are called.

There is an issue here that has more information about the issue.

Obviously, I tried using //go:norace which indeed does remove the race code from the function but the ABI0 wrapper still has the race detector code. The functions are called from assembly since we need to move from the C ABI to Go ABI which forces us into calling the ABI0 wrapper. I can't use <ABIInternal> since that is only allowed in the runtime. As far as I can tell there is no way around the wrapper.

So I was wondering if this is a bug? Shouldn't the //go:norace comment also apply the the ABI wrappers? If not, is there any other suggestions as to how purego could keep functioning when CGO_ENABLED=0 and -race are defined?

I've had a hard time debugging this since no debugger I've tested links to the program before it crashes with SIGSEGV. And there is no stack trace. I may be missing something so I am eager to learn!

Cuong Manh Le

unread,
Nov 30, 2022, 1:24:08 PM11/30/22
to golang-nuts

See my suggestion here: https://github.com/ebitengine/purego/issues/71#issuecomment-1332545306

For //go:norace and ABI wrapper functions, there's no instrument emitted. Your problem is that the compiler know there's a native ABI0 implementation for x_cgo_init, so calling it from assembly is force to use the ABI0 one, not the ABI wrapper.

Jarrett Kuklis

unread,
Nov 30, 2022, 5:27:52 PM11/30/22
to golang-nuts
I tried that and received a SIGBUS

CGO_ENABLED=0 GOARCH=amd64 gotip run -race ./example/main.go 
signal: bus error

Reply all
Reply to author
Forward
0 new messages