diff options
| author | Cherry Mui <cherryyz@google.com> | 2026-02-18 15:25:22 -0500 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2026-02-19 12:22:50 -0800 |
| commit | 839cd82fa53ec481ffcd02e139b3d77c2724892e (patch) | |
| tree | 64d9fa2aee670156b52333cacf83ca91818426cd /src | |
| parent | 06dc5db75d4c2548c0187f34ce79389678be7ca0 (diff) | |
| download | go-839cd82fa53ec481ffcd02e139b3d77c2724892e.tar.xz | |
cmd/cgo/internal/test: add a test for C calling into Go before init done
Test that C code can call back into Go (on a separate thread)
before init is done. The callback should wait for the init done.
And this should not cause a false race.
This corresponds to the runtime fix in CL 746581.
Change-Id: I10e6a9d5fe056be16143f5f6a322f51e56fc9fdf
Reviewed-on: https://go-review.googlesource.com/c/go/+/746780
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/cgo/internal/test/cgo_test.go | 1 | ||||
| -rw-r--r-- | src/cmd/cgo/internal/test/cthread_unix.c | 15 | ||||
| -rw-r--r-- | src/cmd/cgo/internal/test/cthread_windows.c | 16 | ||||
| -rw-r--r-- | src/cmd/cgo/internal/test/testx.go | 26 |
4 files changed, 58 insertions, 0 deletions
diff --git a/src/cmd/cgo/internal/test/cgo_test.go b/src/cmd/cgo/internal/test/cgo_test.go index 17f5f3531c..17f9225cf9 100644 --- a/src/cmd/cgo/internal/test/cgo_test.go +++ b/src/cmd/cgo/internal/test/cgo_test.go @@ -78,6 +78,7 @@ func TestBoolAlign(t *testing.T) { testBoolAlign(t) } func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) } func TestCallback(t *testing.T) { testCallback(t) } func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } +func TestCallbackInInit(t *testing.T) { testCallbackInInit(t) } func TestCallbackGC(t *testing.T) { testCallbackGC(t) } func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) } func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) } diff --git a/src/cmd/cgo/internal/test/cthread_unix.c b/src/cmd/cgo/internal/test/cthread_unix.c index d0da643158..1901c6437f 100644 --- a/src/cmd/cgo/internal/test/cthread_unix.c +++ b/src/cmd/cgo/internal/test/cthread_unix.c @@ -56,3 +56,18 @@ callGoInCThread(int max) return max; } + +static void* +callbackInInitCThread(void* unused) +{ + callbackInInit(); + return NULL; +} + +void +callbackInInitC(void) +{ + pthread_t thread; + + pthread_create(&thread, NULL, callbackInInitCThread, NULL); +} diff --git a/src/cmd/cgo/internal/test/cthread_windows.c b/src/cmd/cgo/internal/test/cthread_windows.c index 4e52209dee..5bfc6f2c48 100644 --- a/src/cmd/cgo/internal/test/cthread_windows.c +++ b/src/cmd/cgo/internal/test/cthread_windows.c @@ -57,3 +57,19 @@ callGoInCThread(int max) CloseHandle((HANDLE)thread_id); return max; } + +__stdcall +static unsigned int +callbackInInitCThread(void* unused) +{ + callbackInInit(); + return 0; +} + +void +callbackInInitC(void) +{ + uintptr_t thread_id; + thread_id = _beginthreadex(0, 0, callbackInInitCThread, NULL, 0, 0); + CloseHandle((HANDLE)thread_id); +} diff --git a/src/cmd/cgo/internal/test/testx.go b/src/cmd/cgo/internal/test/testx.go index 5a6f42e44e..1c5ac99bd2 100644 --- a/src/cmd/cgo/internal/test/testx.go +++ b/src/cmd/cgo/internal/test/testx.go @@ -26,6 +26,7 @@ import ( // threads extern void doAdd(int, int); extern int callGoInCThread(int); +extern void callbackInInitC(void); // issue 1328 void IntoC(void); @@ -622,3 +623,28 @@ func ditCallback() uint8 { } return 0 } + +// Test C calling back into Go before init is done. +// In particular, this does not trigger false race +// (the fix is in CL 746581). + +var callbackInInitVar int + +func init() { + C.callbackInInitC() + callbackInInitVar = 123 +} + +var callbackInInitChan = make(chan int) + +//export callbackInInit +func callbackInInit() { + if callbackInInitVar != 123 { + panic("callbackInInitVar not initialized to 123") + } + callbackInInitChan <- 1 +} + +func testCallbackInInit(t *testing.T) { + <-callbackInInitChan // make sure callbackInInit runs +} |
