aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/testdata/testprogcgo
diff options
context:
space:
mode:
authorKatie Hockman <katie@golang.org>2020-12-14 10:03:05 -0500
committerKatie Hockman <katie@golang.org>2020-12-14 10:06:13 -0500
commit0345ede87ee12698988973884cfc0fd3d499dffd (patch)
tree7123cff141ee5661208d2f5f437b8f5252ac7f6a /src/runtime/testdata/testprogcgo
parent4651d6b267818b0e0d128a5443289717c4bb8cbc (diff)
parent0a02371b0576964e81c3b40d328db9a3ef3b031b (diff)
downloadgo-0345ede87ee12698988973884cfc0fd3d499dffd.tar.xz
[dev.fuzz] all: merge master into dev.fuzz
Change-Id: I5d8c8329ccc9d747bd81ade6b1cb7cb8ae2e94b2
Diffstat (limited to 'src/runtime/testdata/testprogcgo')
-rw-r--r--src/runtime/testdata/testprogcgo/eintr.go3
-rw-r--r--src/runtime/testdata/testprogcgo/exec.go3
-rw-r--r--src/runtime/testdata/testprogcgo/needmdeadlock.go95
-rw-r--r--src/runtime/testdata/testprogcgo/pprof.go3
-rw-r--r--src/runtime/testdata/testprogcgo/threadpprof.go3
-rw-r--r--src/runtime/testdata/testprogcgo/traceback.go79
-rw-r--r--src/runtime/testdata/testprogcgo/traceback_c.c65
7 files changed, 191 insertions, 60 deletions
diff --git a/src/runtime/testdata/testprogcgo/eintr.go b/src/runtime/testdata/testprogcgo/eintr.go
index 791ff1bedc..1722a75eb9 100644
--- a/src/runtime/testdata/testprogcgo/eintr.go
+++ b/src/runtime/testdata/testprogcgo/eintr.go
@@ -32,7 +32,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"log"
"net"
"os"
@@ -242,5 +241,5 @@ func testExec(wg *sync.WaitGroup) {
// Block blocks until stdin is closed.
func Block() {
- io.Copy(ioutil.Discard, os.Stdin)
+ io.Copy(io.Discard, os.Stdin)
}
diff --git a/src/runtime/testdata/testprogcgo/exec.go b/src/runtime/testdata/testprogcgo/exec.go
index 94da5dc526..15723c7369 100644
--- a/src/runtime/testdata/testprogcgo/exec.go
+++ b/src/runtime/testdata/testprogcgo/exec.go
@@ -31,6 +31,7 @@ import "C"
import (
"fmt"
+ "io/fs"
"os"
"os/exec"
"os/signal"
@@ -98,7 +99,7 @@ func CgoExecSignalMask() {
// isEAGAIN reports whether err is an EAGAIN error from a process execution.
func isEAGAIN(err error) bool {
- if p, ok := err.(*os.PathError); ok {
+ if p, ok := err.(*fs.PathError); ok {
err = p.Err
}
return err == syscall.EAGAIN
diff --git a/src/runtime/testdata/testprogcgo/needmdeadlock.go b/src/runtime/testdata/testprogcgo/needmdeadlock.go
new file mode 100644
index 0000000000..5a9c359006
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/needmdeadlock.go
@@ -0,0 +1,95 @@
+// Copyright 2020 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.
+
+// +build !plan9,!windows
+
+package main
+
+// This is for issue #42207.
+// During a call to needm we could get a SIGCHLD signal
+// which would itself call needm, causing a deadlock.
+
+/*
+#include <signal.h>
+#include <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+
+extern void GoNeedM();
+
+#define SIGNALERS 10
+
+static void* needmSignalThread(void* p) {
+ pthread_t* pt = (pthread_t*)(p);
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ if (pthread_kill(*pt, SIGCHLD) < 0) {
+ return NULL;
+ }
+ usleep(1);
+ }
+ return NULL;
+}
+
+// We don't need many calls, as the deadlock is only likely
+// to occur the first couple of times that needm is called.
+// After that there will likely be an extra M available.
+#define CALLS 10
+
+static void* needmCallbackThread(void* p) {
+ int i;
+
+ for (i = 0; i < SIGNALERS; i++) {
+ sched_yield(); // Help the signal threads get started.
+ }
+ for (i = 0; i < CALLS; i++) {
+ GoNeedM();
+ }
+ return NULL;
+}
+
+static void runNeedmSignalThread() {
+ int i;
+ pthread_t caller;
+ pthread_t s[SIGNALERS];
+
+ pthread_create(&caller, NULL, needmCallbackThread, NULL);
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_create(&s[i], NULL, needmSignalThread, &caller);
+ }
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_join(s[i], NULL);
+ }
+ pthread_join(caller, NULL);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "time"
+)
+
+func init() {
+ register("NeedmDeadlock", NeedmDeadlock)
+}
+
+//export GoNeedM
+func GoNeedM() {
+}
+
+func NeedmDeadlock() {
+ // The failure symptom is that the program hangs because of a
+ // deadlock in needm, so set an alarm.
+ go func() {
+ time.Sleep(5 * time.Second)
+ fmt.Println("Hung for 5 seconds")
+ os.Exit(1)
+ }()
+
+ C.runNeedmSignalThread()
+ fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go
index 00f2c42e93..3b73fa0bdd 100644
--- a/src/runtime/testdata/testprogcgo/pprof.go
+++ b/src/runtime/testdata/testprogcgo/pprof.go
@@ -60,7 +60,6 @@ import "C"
import (
"fmt"
- "io/ioutil"
"os"
"runtime"
"runtime/pprof"
@@ -75,7 +74,7 @@ func init() {
func CgoPprof() {
runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoTraceback), nil, nil)
- f, err := ioutil.TempFile("", "prof")
+ f, err := os.CreateTemp("", "prof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go
index 37a2a1ab65..feb774ba59 100644
--- a/src/runtime/testdata/testprogcgo/threadpprof.go
+++ b/src/runtime/testdata/testprogcgo/threadpprof.go
@@ -74,7 +74,6 @@ import "C"
import (
"fmt"
- "io/ioutil"
"os"
"runtime"
"runtime/pprof"
@@ -97,7 +96,7 @@ func CgoPprofThreadNoTraceback() {
}
func pprofThread() {
- f, err := ioutil.TempFile("", "prof")
+ f, err := os.CreateTemp("", "prof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprogcgo/traceback.go b/src/runtime/testdata/testprogcgo/traceback.go
index 2a023f66ca..e2d7599131 100644
--- a/src/runtime/testdata/testprogcgo/traceback.go
+++ b/src/runtime/testdata/testprogcgo/traceback.go
@@ -11,58 +11,11 @@ package main
/*
#cgo CFLAGS: -g -O0
-#include <stdint.h>
-
-char *p;
-
-static int f3(void) {
- *p = 0;
- return 0;
-}
-
-static int f2(void) {
- return f3();
-}
-
-static int f1(void) {
- return f2();
-}
-
-struct cgoTracebackArg {
- uintptr_t context;
- uintptr_t sigContext;
- uintptr_t* buf;
- uintptr_t max;
-};
-
-struct cgoSymbolizerArg {
- uintptr_t pc;
- const char* file;
- uintptr_t lineno;
- const char* func;
- uintptr_t entry;
- uintptr_t more;
- uintptr_t data;
-};
-
-void cgoTraceback(void* parg) {
- struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
- arg->buf[0] = 1;
- arg->buf[1] = 2;
- arg->buf[2] = 3;
- arg->buf[3] = 0;
-}
-
-void cgoSymbolizer(void* parg) {
- struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg);
- if (arg->pc != arg->data + 1) {
- arg->file = "unexpected data";
- } else {
- arg->file = "cgo symbolizer";
- }
- arg->lineno = arg->data + 1;
- arg->data++;
-}
+// Defined in traceback_c.c.
+extern int crashInGo;
+int tracebackF1(void);
+void cgoTraceback(void* parg);
+void cgoSymbolizer(void* parg);
*/
import "C"
@@ -73,9 +26,29 @@ import (
func init() {
register("CrashTraceback", CrashTraceback)
+ register("CrashTracebackGo", CrashTracebackGo)
}
func CrashTraceback() {
runtime.SetCgoTraceback(0, unsafe.Pointer(C.cgoTraceback), nil, unsafe.Pointer(C.cgoSymbolizer))
- C.f1()
+ C.tracebackF1()
+}
+
+func CrashTracebackGo() {
+ C.crashInGo = 1
+ CrashTraceback()
+}
+
+//export h1
+func h1() {
+ h2()
+}
+
+func h2() {
+ h3()
+}
+
+func h3() {
+ var x *int
+ *x = 0
}
diff --git a/src/runtime/testdata/testprogcgo/traceback_c.c b/src/runtime/testdata/testprogcgo/traceback_c.c
new file mode 100644
index 0000000000..56eda8fa8c
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/traceback_c.c
@@ -0,0 +1,65 @@
+// Copyright 2020 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.
+
+// The C definitions for traceback.go. That file uses //export so
+// it can't put function definitions in the "C" import comment.
+
+#include <stdint.h>
+
+char *p;
+
+int crashInGo;
+extern void h1(void);
+
+int tracebackF3(void) {
+ if (crashInGo)
+ h1();
+ else
+ *p = 0;
+ return 0;
+}
+
+int tracebackF2(void) {
+ return tracebackF3();
+}
+
+int tracebackF1(void) {
+ return tracebackF2();
+}
+
+struct cgoTracebackArg {
+ uintptr_t context;
+ uintptr_t sigContext;
+ uintptr_t* buf;
+ uintptr_t max;
+};
+
+struct cgoSymbolizerArg {
+ uintptr_t pc;
+ const char* file;
+ uintptr_t lineno;
+ const char* func;
+ uintptr_t entry;
+ uintptr_t more;
+ uintptr_t data;
+};
+
+void cgoTraceback(void* parg) {
+ struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
+ arg->buf[0] = 1;
+ arg->buf[1] = 2;
+ arg->buf[2] = 3;
+ arg->buf[3] = 0;
+}
+
+void cgoSymbolizer(void* parg) {
+ struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg);
+ if (arg->pc != arg->data + 1) {
+ arg->file = "unexpected data";
+ } else {
+ arg->file = "cgo symbolizer";
+ }
+ arg->lineno = arg->data + 1;
+ arg->data++;
+}