diff options
author | Ian Lance Taylor <iant@golang.org> | 2023-03-07 20:27:59 -0800 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-03-08 20:11:59 +0000 |
commit | 618fb4ab068272cc87b137d9fc527210be4b8ad2 (patch) | |
tree | 690ef06a2fb231e639e5ba7f3c4a617d1fa574fe /misc | |
parent | 54d05e4e252298724c5615ea2a4e36f2151b22ce (diff) | |
download | go-618fb4ab068272cc87b137d9fc527210be4b8ad2.tar.gz go-618fb4ab068272cc87b137d9fc527210be4b8ad2.zip |
runtime/cgo: add tsan sync for traceback function
Change-Id: Ifb8d64f18b67c8b712feec29ffb6719c6e9718ec
Reviewed-on: https://go-review.googlesource.com/c/go/+/474198
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'misc')
-rw-r--r-- | misc/cgo/testsanitizers/testdata/tsan13.go | 90 | ||||
-rw-r--r-- | misc/cgo/testsanitizers/tsan_test.go | 4 |
2 files changed, 94 insertions, 0 deletions
diff --git a/misc/cgo/testsanitizers/testdata/tsan13.go b/misc/cgo/testsanitizers/testdata/tsan13.go new file mode 100644 index 0000000000..ebdf63581b --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/tsan13.go @@ -0,0 +1,90 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// This program failed when run under the C/C++ ThreadSanitizer. +// There was no TSAN synchronization for the call to the cgo +// traceback routine. + +/* +#cgo CFLAGS: -g -fsanitize=thread +#cgo LDFLAGS: -g -fsanitize=thread + +#include <pthread.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/time.h> +#include <unistd.h> + +struct tracebackArg { + uintptr_t Context; + uintptr_t SigContext; + uintptr_t* Buf; + uintptr_t Max; +}; + +void tsanTraceback(struct tracebackArg *arg) { + arg->Buf[0] = 0; +} + +static void* spin(void *arg) { + size_t n; + struct timeval tvstart, tvnow; + int diff; + void *prev; + void *cur; + + prev = NULL; + gettimeofday(&tvstart, NULL); + for (n = 0; n < 1<<20; n++) { + cur = malloc(n); + free(prev); + prev = cur; + + gettimeofday(&tvnow, NULL); + diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); + + // Profile frequency is 100Hz so we should definitely + // get some signals in 50 milliseconds. + if (diff > 50 * 1000) { + break; + } + } + + free(prev); + + return NULL; +} + +static void runThreads(int n) { + pthread_t ids[64]; + int i; + + if (n > 64) { + n = 64; + } + for (i = 0; i < n; i++) { + pthread_create(&ids[i], NULL, spin, NULL); + } + for (i = 0; i < n; i++) { + pthread_join(ids[i], NULL); + } +} +*/ +import "C" + +import ( + "io" + "runtime" + "runtime/pprof" + "unsafe" +) + +func main() { + runtime.SetCgoTraceback(0, unsafe.Pointer(C.tsanTraceback), nil, nil) + pprof.StartCPUProfile(io.Discard) + C.runThreads(C.int(runtime.GOMAXPROCS(0))) + pprof.StopCPUProfile() +} diff --git a/misc/cgo/testsanitizers/tsan_test.go b/misc/cgo/testsanitizers/tsan_test.go index 00ad313b9c..f65d842363 100644 --- a/misc/cgo/testsanitizers/tsan_test.go +++ b/misc/cgo/testsanitizers/tsan_test.go @@ -46,6 +46,7 @@ func TestTSAN(t *testing.T) { {src: "tsan10.go", needsRuntime: true}, {src: "tsan11.go", needsRuntime: true}, {src: "tsan12.go", needsRuntime: true}, + {src: "tsan13.go", needsRuntime: true}, } for _, tc := range cases { tc := tc @@ -63,6 +64,9 @@ func TestTSAN(t *testing.T) { if tc.needsRuntime { config.skipIfRuntimeIncompatible(t) } + // If we don't see halt_on_error, the program + // will only exit non-zero if we call C.exit. + cmd.Env = append(cmd.Environ(), "TSAN_OPTIONS=halt_on_error=1") mustRun(t, cmd) }) } |