summaryrefslogtreecommitdiffstats
path: root/src/runtime/testdata/testprogcgo/threadprof.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
commit73df946d56c74384511a194dd01dbe099584fd1a (patch)
treefd0bcea490dd81327ddfbb31e215439672c9a068 /src/runtime/testdata/testprogcgo/threadprof.go
parentInitial commit. (diff)
downloadgolang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.tar.xz
golang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.zip
Adding upstream version 1.16.10.upstream/1.16.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/runtime/testdata/testprogcgo/threadprof.go')
-rw-r--r--src/runtime/testdata/testprogcgo/threadprof.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go
new file mode 100644
index 0000000..2d4c103
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadprof.go
@@ -0,0 +1,98 @@
+// Copyright 2015 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.
+
+// We only build this file with the tag "threadprof", since it starts
+// a thread running a busy loop at constructor time.
+
+// +build !plan9,!windows
+// +build threadprof
+
+package main
+
+/*
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+
+volatile int32_t spinlock;
+
+static void *thread1(void *p) {
+ (void)p;
+ while (spinlock == 0)
+ ;
+ pthread_kill(pthread_self(), SIGPROF);
+ spinlock = 0;
+ return NULL;
+}
+
+__attribute__((constructor)) void issue9456() {
+ pthread_t tid;
+ pthread_create(&tid, 0, thread1, NULL);
+}
+
+void **nullptr;
+
+void *crash(void *p) {
+ *nullptr = p;
+ return 0;
+}
+
+int start_crashing_thread(void) {
+ pthread_t tid;
+ return pthread_create(&tid, 0, crash, 0);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "runtime"
+ "sync/atomic"
+ "time"
+ "unsafe"
+)
+
+func init() {
+ register("CgoExternalThreadSIGPROF", CgoExternalThreadSIGPROF)
+ register("CgoExternalThreadSignal", CgoExternalThreadSignal)
+}
+
+func CgoExternalThreadSIGPROF() {
+ // This test intends to test that sending SIGPROF to foreign threads
+ // before we make any cgo call will not abort the whole process, so
+ // we cannot make any cgo call here. See https://golang.org/issue/9456.
+ atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
+ for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
+ runtime.Gosched()
+ }
+ println("OK")
+}
+
+func CgoExternalThreadSignal() {
+ if len(os.Args) > 2 && os.Args[2] == "crash" {
+ i := C.start_crashing_thread()
+ if i != 0 {
+ fmt.Println("pthread_create failed:", i)
+ // Exit with 0 because parent expects us to crash.
+ return
+ }
+
+ // We should crash immediately, but give it plenty of
+ // time before failing (by exiting 0) in case we are
+ // running on a slow system.
+ time.Sleep(5 * time.Second)
+ return
+ }
+
+ out, err := exec.Command(os.Args[0], "CgoExternalThreadSignal", "crash").CombinedOutput()
+ if err == nil {
+ fmt.Println("C signal did not crash as expected")
+ fmt.Printf("\n%s\n", out)
+ os.Exit(1)
+ }
+
+ fmt.Println("OK")
+}