aboutsummaryrefslogtreecommitdiff
path: root/libgo/misc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-09-14 17:11:35 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-09-14 17:11:35 +0000
commitbc998d034f45d1828a8663b2eed928faf22a7d01 (patch)
tree8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/misc
parenta41a6142df74219f596e612d3a7775f68ca6e96f (diff)
downloadgcc-bc998d034f45d1828a8663b2eed928faf22a7d01.zip
gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.gz
gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.bz2
libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753 From-SVN: r252767
Diffstat (limited to 'libgo/misc')
-rw-r--r--libgo/misc/cgo/errors/issue18452.go18
-rw-r--r--libgo/misc/cgo/errors/issue18889.go7
-rw-r--r--libgo/misc/cgo/errors/ptr.go8
-rw-r--r--libgo/misc/cgo/errors/test.bash4
-rw-r--r--libgo/misc/cgo/fortran/test.bash2
-rw-r--r--libgo/misc/cgo/test/cgo_test.go4
-rw-r--r--libgo/misc/cgo/test/issue18720.go28
-rw-r--r--libgo/misc/cgo/test/issue20129.go33
-rw-r--r--libgo/misc/cgo/test/issue20266.go21
-rw-r--r--libgo/misc/cgo/test/issue20266/issue20266.h9
-rw-r--r--libgo/misc/cgo/test/issue20369.go20
-rw-r--r--libgo/misc/cgo/test/issue6612.go17
-rw-r--r--libgo/misc/cgo/testcarchive/carchive_test.go170
-rw-r--r--libgo/misc/cgo/testcarchive/main2.c35
-rw-r--r--libgo/misc/cgo/testcarchive/main3.c34
-rw-r--r--libgo/misc/cgo/testcarchive/main5.c18
-rw-r--r--libgo/misc/cgo/testcarchive/main6.c34
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go30
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go12
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go25
-rw-r--r--libgo/misc/cgo/testcshared/main0.c6
-rw-r--r--libgo/misc/cgo/testcshared/src/p/p.go3
-rw-r--r--libgo/misc/cgo/testcshared/test.bash20
-rw-r--r--libgo/misc/cgo/testplugin/src/issue19534/main.go23
-rw-r--r--libgo/misc/cgo/testplugin/src/issue19534/plugin.go9
-rw-r--r--libgo/misc/cgo/testplugin/test.bash8
-rw-r--r--libgo/misc/cgo/testplugin/unnamed1.go11
-rw-r--r--libgo/misc/cgo/testplugin/unnamed2.go9
-rw-r--r--libgo/misc/cgo/testsanitizers/test.bash57
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan10.go31
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan11.go55
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan12.go35
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan_shared.go63
-rw-r--r--libgo/misc/cgo/testshared/shared_test.go20
-rw-r--r--libgo/misc/cgo/testshared/src/division/division.go17
35 files changed, 813 insertions, 83 deletions
diff --git a/libgo/misc/cgo/errors/issue18452.go b/libgo/misc/cgo/errors/issue18452.go
new file mode 100644
index 0000000..36ef7f5
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue18452.go
@@ -0,0 +1,18 @@
+// Copyright 2017 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.
+
+// Issue 18452: show pos info in undefined name errors
+
+package p
+
+import (
+ "C"
+ "fmt"
+)
+
+func a() {
+ fmt.Println("Hello, world!")
+ C.function_that_does_not_exist() // line 16
+ C.pi // line 17
+}
diff --git a/libgo/misc/cgo/errors/issue18889.go b/libgo/misc/cgo/errors/issue18889.go
new file mode 100644
index 0000000..bba6b8f
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue18889.go
@@ -0,0 +1,7 @@
+package main
+
+import "C"
+
+func main() {
+ _ = C.malloc // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/ptr.go b/libgo/misc/cgo/errors/ptr.go
index 4dafbdf..3e11766 100644
--- a/libgo/misc/cgo/errors/ptr.go
+++ b/libgo/misc/cgo/errors/ptr.go
@@ -343,6 +343,14 @@ var ptrTests = []ptrTest{
body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
fail: false,
},
+ {
+ // Issue #21306.
+ name: "preempt-during-call",
+ c: `void f() {}`,
+ imports: []string{"runtime", "sync"},
+ body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`,
+ fail: false,
+ },
}
func main() {
diff --git a/libgo/misc/cgo/errors/test.bash b/libgo/misc/cgo/errors/test.bash
index 05261e9..ed0b094 100644
--- a/libgo/misc/cgo/errors/test.bash
+++ b/libgo/misc/cgo/errors/test.bash
@@ -17,7 +17,7 @@ check() {
expect() {
file=$1
shift
- if go build $file >errs 2>&1; then
+ if go build -gcflags=-C $file >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
exit 1
fi
@@ -47,6 +47,8 @@ expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulongl
check issue13830.go
check issue16116.go
check issue16591.go
+check issue18889.go
+expect issue18452.go issue18452.go:16 issue18452.go:17
if ! go build issue14669.go; then
exit 1
diff --git a/libgo/misc/cgo/fortran/test.bash b/libgo/misc/cgo/fortran/test.bash
index 3d1bc9d..1e0d59e 100644
--- a/libgo/misc/cgo/fortran/test.bash
+++ b/libgo/misc/cgo/fortran/test.bash
@@ -12,7 +12,7 @@ FC=$1
goos=$(go env GOOS)
libext="so"
-if [ "$goos" == "darwin" ]; then
+if [ "$goos" = "darwin" ]; then
libext="dylib"
fi
diff --git a/libgo/misc/cgo/test/cgo_test.go b/libgo/misc/cgo/test/cgo_test.go
index a6de999..f7cf6f6 100644
--- a/libgo/misc/cgo/test/cgo_test.go
+++ b/libgo/misc/cgo/test/cgo_test.go
@@ -76,5 +76,9 @@ func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
func TestCheckConst(t *testing.T) { testCheckConst(t) }
func Test17537(t *testing.T) { test17537(t) }
func Test18126(t *testing.T) { test18126(t) }
+func Test20369(t *testing.T) { test20369(t) }
+func Test18720(t *testing.T) { test18720(t) }
+func Test20266(t *testing.T) { test20266(t) }
+func Test20129(t *testing.T) { test20129(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/libgo/misc/cgo/test/issue18720.go b/libgo/misc/cgo/test/issue18720.go
new file mode 100644
index 0000000..a933044
--- /dev/null
+++ b/libgo/misc/cgo/test/issue18720.go
@@ -0,0 +1,28 @@
+// Copyright 2017 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 cgotest
+
+/*
+#define HELLO "hello"
+#define WORLD "world"
+#define HELLO_WORLD HELLO "\000" WORLD
+
+struct foo { char c; };
+#define SIZE_OF(x) sizeof(x)
+#define SIZE_OF_FOO SIZE_OF(struct foo)
+*/
+import "C"
+import "testing"
+
+func test18720(t *testing.T) {
+ if C.HELLO_WORLD != "hello\000world" {
+ t.Fatalf(`expected "hello\000world", but got %q`, C.HELLO_WORLD)
+ }
+
+ // Issue 20125.
+ if got, want := C.SIZE_OF_FOO, 1; got != want {
+ t.Errorf("C.SIZE_OF_FOO == %v, expected %v", got, want)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue20129.go b/libgo/misc/cgo/test/issue20129.go
new file mode 100644
index 0000000..e69e0e1
--- /dev/null
+++ b/libgo/misc/cgo/test/issue20129.go
@@ -0,0 +1,33 @@
+// Copyright 2017 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 cgotest
+
+/*
+int issue20129 = 0;
+typedef void issue20129Void;
+issue20129Void issue20129Foo() {
+ issue20129 = 1;
+}
+typedef issue20129Void issue20129Void2;
+issue20129Void2 issue20129Bar() {
+ issue20129 = 2;
+}
+*/
+import "C"
+import "testing"
+
+func test20129(t *testing.T) {
+ if C.issue20129 != 0 {
+ t.Fatal("test is broken")
+ }
+ C.issue20129Foo()
+ if C.issue20129 != 1 {
+ t.Errorf("got %v but expected %v", C.issue20129, 1)
+ }
+ C.issue20129Bar()
+ if C.issue20129 != 2 {
+ t.Errorf("got %v but expected %v", C.issue20129, 2)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue20266.go b/libgo/misc/cgo/test/issue20266.go
new file mode 100644
index 0000000..9f95086
--- /dev/null
+++ b/libgo/misc/cgo/test/issue20266.go
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+// Issue 20266: use -I with a relative path.
+
+package cgotest
+
+/*
+#cgo CFLAGS: -I issue20266 -Iissue20266 -Ddef20266
+#include "issue20266.h"
+*/
+import "C"
+
+import "testing"
+
+func test20266(t *testing.T) {
+ if got, want := C.issue20266, 20266; got != want {
+ t.Errorf("got %d, want %d", got, want)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue20266/issue20266.h b/libgo/misc/cgo/test/issue20266/issue20266.h
new file mode 100644
index 0000000..8d3258e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue20266/issue20266.h
@@ -0,0 +1,9 @@
+// Copyright 2017 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.
+
+#define issue20266 20266
+
+#ifndef def20266
+#error "expected def20266 to be defined"
+#endif
diff --git a/libgo/misc/cgo/test/issue20369.go b/libgo/misc/cgo/test/issue20369.go
new file mode 100644
index 0000000..37b4b78
--- /dev/null
+++ b/libgo/misc/cgo/test/issue20369.go
@@ -0,0 +1,20 @@
+// Copyright 2017 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 cgotest
+
+/*
+#define UINT64_MAX 18446744073709551615ULL
+*/
+import "C"
+import (
+ "math"
+ "testing"
+)
+
+func test20369(t *testing.T) {
+ if C.UINT64_MAX != math.MaxUint64 {
+ t.Fatalf("got %v, want %v", uint64(C.UINT64_MAX), uint64(math.MaxUint64))
+ }
+}
diff --git a/libgo/misc/cgo/test/issue6612.go b/libgo/misc/cgo/test/issue6612.go
index c337f91..15a12fa 100644
--- a/libgo/misc/cgo/test/issue6612.go
+++ b/libgo/misc/cgo/test/issue6612.go
@@ -74,18 +74,15 @@ func testNaming(t *testing.T) {
}
}
- // This would be nice, but it has never worked.
- /*
- if c := C.myfloat_def; c != 1.5 {
- t.Errorf("C.myint_def = %v, want 1.5", c)
- }
- {
- const c = C.myfloat_def
- if c != 1.5 {
+ if c := C.myfloat_def; c != 1.5 {
+ t.Errorf("C.myint_def = %v, want 1.5", c)
+ }
+ {
+ const c = C.myfloat_def
+ if c != 1.5 {
t.Errorf("C.myint as const = %v, want 1.5", c)
- }
}
- */
+ }
if s := C.mystring_def; s != "hello" {
t.Errorf("C.mystring_def = %q, want %q", s, "hello")
diff --git a/libgo/misc/cgo/testcarchive/carchive_test.go b/libgo/misc/cgo/testcarchive/carchive_test.go
index a2ad9c5..4865b80 100644
--- a/libgo/misc/cgo/testcarchive/carchive_test.go
+++ b/libgo/misc/cgo/testcarchive/carchive_test.go
@@ -120,8 +120,10 @@ func init() {
func goEnv(key string) string {
out, err := exec.Command("go", "env", key).Output()
if err != nil {
- fmt.Fprintf(os.Stderr, "go env %s failed:\n%s", key, err)
- fmt.Fprintf(os.Stderr, "%s", err.(*exec.ExitError).Stderr)
+ fmt.Fprintf(os.Stderr, "go env %s failed:\n%s\n", key, err)
+ if ee, ok := err.(*exec.ExitError); ok {
+ fmt.Fprintf(os.Stderr, "%s", ee.Stderr)
+ }
os.Exit(2)
}
return strings.TrimSpace(string(out))
@@ -238,15 +240,7 @@ func TestEarlySignalHandler(t *testing.T) {
}
func TestSignalForwarding(t *testing.T) {
- switch GOOS {
- case "darwin":
- switch GOARCH {
- case "arm", "arm64":
- t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
- }
- case "windows":
- t.Skip("skipping signal test on Windows")
- }
+ checkSignalForwardingTest(t)
defer func() {
os.Remove("libgo2.a")
@@ -274,32 +268,19 @@ func TestSignalForwarding(t *testing.T) {
cmd = exec.Command(bin[0], append(bin[1:], "1")...)
out, err := cmd.CombinedOutput()
+ t.Logf("%s", out)
+ expectSignal(t, err, syscall.SIGSEGV)
- if err == nil {
- t.Logf("%s", out)
- t.Error("test program succeeded unexpectedly")
- } else if ee, ok := err.(*exec.ExitError); !ok {
- t.Logf("%s", out)
- t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
- } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
- t.Logf("%s", out)
- t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
- } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
- t.Logf("%s", out)
- t.Errorf("got %v; expected SIGSEGV", ee)
- }
+ // Test SIGPIPE forwarding
+ cmd = exec.Command(bin[0], append(bin[1:], "3")...)
+
+ out, err = cmd.CombinedOutput()
+ t.Logf("%s", out)
+ expectSignal(t, err, syscall.SIGPIPE)
}
func TestSignalForwardingExternal(t *testing.T) {
- switch GOOS {
- case "darwin":
- switch GOARCH {
- case "arm", "arm64":
- t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
- }
- case "windows":
- t.Skip("skipping signal test on Windows")
- }
+ checkSignalForwardingTest(t)
defer func() {
os.Remove("libgo2.a")
@@ -370,14 +351,7 @@ func TestSignalForwardingExternal(t *testing.T) {
continue
}
- if ee, ok := err.(*exec.ExitError); !ok {
- t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
- } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
- t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
- } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
- t.Errorf("got %v; expected SIGSEGV", ee)
- } else {
- // We got the error we expected.
+ if expectSignal(t, err, syscall.SIGSEGV) {
return
}
}
@@ -385,6 +359,38 @@ func TestSignalForwardingExternal(t *testing.T) {
t.Errorf("program succeeded unexpectedly %d times", tries)
}
+// checkSignalForwardingTest calls t.Skip if the SignalForwarding test
+// doesn't work on this platform.
+func checkSignalForwardingTest(t *testing.T) {
+ switch GOOS {
+ case "darwin":
+ switch GOARCH {
+ case "arm", "arm64":
+ t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+ }
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+}
+
+// expectSignal checks that err, the exit status of a test program,
+// shows a failure due to a specific signal. Returns whether we found
+// the expected signal.
+func expectSignal(t *testing.T, err error, sig syscall.Signal) bool {
+ if err == nil {
+ t.Error("test program succeeded unexpectedly")
+ } else if ee, ok := err.(*exec.ExitError); !ok {
+ t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+ } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+ t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+ } else if !ws.Signaled() || ws.Signal() != sig {
+ t.Errorf("got %v; expected signal %v", ee, sig)
+ } else {
+ return true
+ }
+ return false
+}
+
func TestOsSignal(t *testing.T) {
switch GOOS {
case "windows":
@@ -585,3 +591,85 @@ func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
}
return false
}
+
+func TestSIGPROF(t *testing.T) {
+ switch GOOS {
+ case "windows", "plan9":
+ t.Skipf("skipping SIGPROF test on %s", GOOS)
+ }
+
+ t.Parallel()
+
+ defer func() {
+ os.Remove("testp6" + exeSuffix)
+ os.Remove("libgo6.a")
+ os.Remove("libgo6.h")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "libgo6")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ argv := cmdToRun("./testp6")
+ cmd = exec.Command(argv[0], argv[1:]...)
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+}
+
+// TestCompileWithoutShared tests that if we compile code without the
+// -shared option, we can put it into an archive. When we use the go
+// tool with -buildmode=c-archive, it passes -shared to the compiler,
+// so we override that. The go tool doesn't work this way, but Bazel
+// will likely do it in the future. And it ought to work. This test
+// was added because at one time it did not work on PPC GNU/Linux.
+func TestCompileWithoutShared(t *testing.T) {
+ // For simplicity, reuse the signal forwarding test.
+ checkSignalForwardingTest(t)
+
+ defer func() {
+ os.Remove("libgo2.a")
+ os.Remove("libgo2.h")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "libgo2")
+ cmd.Env = gopathEnv
+ t.Log(cmd.Args)
+ out, err := cmd.CombinedOutput()
+ t.Logf("%s", out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exe := "./testnoshared" + exeSuffix
+ ccArgs := append(cc, "-o", exe, "main5.c", "libgo2.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ t.Log(ccArgs)
+ out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%s", out)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(exe)
+
+ binArgs := append(cmdToRun(exe), "3")
+ t.Log(binArgs)
+ out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
+ t.Logf("%s", out)
+ expectSignal(t, err, syscall.SIGPIPE)
+}
diff --git a/libgo/misc/cgo/testcarchive/main2.c b/libgo/misc/cgo/testcarchive/main2.c
index 774e014..769cd49 100644
--- a/libgo/misc/cgo/testcarchive/main2.c
+++ b/libgo/misc/cgo/testcarchive/main2.c
@@ -17,6 +17,7 @@
#include <unistd.h>
#include <sched.h>
#include <time.h>
+#include <errno.h>
#include "libgo2.h"
@@ -26,6 +27,7 @@ static void die(const char* msg) {
}
static volatile sig_atomic_t sigioSeen;
+static volatile sig_atomic_t sigpipeSeen;
// Use up some stack space.
static void recur(int i, char *p) {
@@ -37,6 +39,10 @@ static void recur(int i, char *p) {
}
}
+static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigpipeSeen = 1;
+}
+
// Signal handler that uses up more stack space than a goroutine will have.
static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
char a[1024];
@@ -106,6 +112,10 @@ static void init() {
die("sigaction");
}
+ sa.sa_sigaction = pipeHandler;
+ if (sigaction(SIGPIPE, &sa, NULL) < 0) {
+ die("sigaction");
+ }
}
int main(int argc, char** argv) {
@@ -167,7 +177,30 @@ int main(int argc, char** argv) {
nanosleep(&ts, NULL);
i++;
if (i > 5000) {
- fprintf(stderr, "looping too long waiting for signal\n");
+ fprintf(stderr, "looping too long waiting for SIGIO\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (verbose) {
+ printf("provoking SIGPIPE\n");
+ }
+
+ GoRaiseSIGPIPE();
+
+ if (verbose) {
+ printf("waiting for sigpipeSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigpipeSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for SIGPIPE\n");
exit(EXIT_FAILURE);
}
}
diff --git a/libgo/misc/cgo/testcarchive/main3.c b/libgo/misc/cgo/testcarchive/main3.c
index 0a6c0d3..60a16cf 100644
--- a/libgo/misc/cgo/testcarchive/main3.c
+++ b/libgo/misc/cgo/testcarchive/main3.c
@@ -11,6 +11,7 @@
#include <string.h>
#include <time.h>
#include <sched.h>
+#include <unistd.h>
#include "libgo3.h"
@@ -25,6 +26,31 @@ static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
sigioSeen = 1;
}
+// Set up the SIGPIPE signal handler in a high priority constructor, so
+// that it is installed before the Go code starts.
+
+static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
+ const char *s = "unexpected SIGPIPE\n";
+ write(2, s, strlen(s));
+ exit(EXIT_FAILURE);
+}
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = pipeHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGPIPE, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+}
+
int main(int argc, char** argv) {
int verbose;
struct sigaction sa;
@@ -35,6 +61,14 @@ int main(int argc, char** argv) {
setvbuf(stdout, NULL, _IONBF, 0);
if (verbose) {
+ printf("raising SIGPIPE\n");
+ }
+
+ // Test that the Go runtime handles SIGPIPE, even if we installed
+ // a non-default SIGPIPE handler before the runtime initializes.
+ ProvokeSIGPIPE();
+
+ if (verbose) {
printf("calling sigaction\n");
}
diff --git a/libgo/misc/cgo/testcarchive/main5.c b/libgo/misc/cgo/testcarchive/main5.c
index 9fadf08..2437bf0 100644
--- a/libgo/misc/cgo/testcarchive/main5.c
+++ b/libgo/misc/cgo/testcarchive/main5.c
@@ -68,6 +68,24 @@ int main(int argc, char** argv) {
break;
}
+ case 3: {
+ if (verbose) {
+ printf("attempting SIGPIPE\n");
+ }
+
+ int fd[2];
+ if (pipe(fd) != 0) {
+ printf("pipe(2) failed\n");
+ return 0;
+ }
+ // Close the reading end.
+ close(fd[0]);
+ // Expect that write(2) fails (EPIPE)
+ if (write(fd[1], "some data", 9) != -1) {
+ printf("write(2) unexpectedly succeeded\n");
+ return 0;
+ }
+ }
default:
printf("Unknown test: %d\n", test);
return 0;
diff --git a/libgo/misc/cgo/testcarchive/main6.c b/libgo/misc/cgo/testcarchive/main6.c
new file mode 100644
index 0000000..2745eb9
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main6.c
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Test that using the Go profiler in a C program does not crash.
+
+#include <stddef.h>
+#include <sys/time.h>
+
+#include "libgo6.h"
+
+int main(int argc, char **argv) {
+ struct timeval tvstart, tvnow;
+ int diff;
+
+ gettimeofday(&tvstart, NULL);
+
+ go_start_profile();
+
+ // Busy wait so we have something to profile.
+ // If we just sleep the profiling signal will never fire.
+ while (1) {
+ 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 a signal in 50 milliseconds.
+ if (diff > 50 * 1000)
+ break;
+ }
+
+ go_stop_profile();
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go b/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
index fbed493..19c8e1a 100644
--- a/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
+++ b/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
@@ -4,6 +4,30 @@
package main
+/*
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+// Raise SIGPIPE.
+static void CRaiseSIGPIPE() {
+ int fds[2];
+
+ if (pipe(fds) == -1) {
+ perror("pipe");
+ exit(EXIT_FAILURE);
+ }
+ // Close the reader end
+ close(fds[0]);
+ // Write to the writer end to provoke a SIGPIPE
+ if (write(fds[1], "some data", 9) != -1) {
+ fprintf(stderr, "write to a closed pipe succeeded\n");
+ exit(EXIT_FAILURE);
+ }
+ close(fds[1]);
+}
+*/
import "C"
import (
@@ -46,5 +70,11 @@ func TestSEGV() {
func Noop() {
}
+// Raise SIGPIPE.
+//export GoRaiseSIGPIPE
+func GoRaiseSIGPIPE() {
+ C.CRaiseSIGPIPE()
+}
+
func main() {
}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go b/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
index 94e5d21c..e276a3c 100644
--- a/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
+++ b/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
@@ -40,5 +40,17 @@ func SawSIGIO() C.int {
}
}
+// ProvokeSIGPIPE provokes a kernel-initiated SIGPIPE.
+//export ProvokeSIGPIPE
+func ProvokeSIGPIPE() {
+ r, w, err := os.Pipe()
+ if err != nil {
+ panic(err)
+ }
+ r.Close()
+ defer w.Close()
+ w.Write([]byte("some data"))
+}
+
func main() {
}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go b/libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go
new file mode 100644
index 0000000..4cb05dc
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go
@@ -0,0 +1,25 @@
+// Copyright 2016 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
+
+import (
+ "io/ioutil"
+ "runtime/pprof"
+)
+
+import "C"
+
+//export go_start_profile
+func go_start_profile() {
+ pprof.StartCPUProfile(ioutil.Discard)
+}
+
+//export go_stop_profile
+func go_stop_profile() {
+ pprof.StopCPUProfile()
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/main0.c b/libgo/misc/cgo/testcshared/main0.c
index 1274b89..39ef7e3 100644
--- a/libgo/misc/cgo/testcshared/main0.c
+++ b/libgo/misc/cgo/testcshared/main0.c
@@ -12,6 +12,7 @@
// int8_t DidInitRun();
// int8_t DidMainRun();
// int32_t FromPkg();
+// uint32_t Divu(uint32_t, uint32_t);
int main(void) {
int8_t ran_init = DidInitRun();
if (!ran_init) {
@@ -30,6 +31,11 @@ int main(void) {
fprintf(stderr, "ERROR: FromPkg=%d, want %d\n", from_pkg, 1024);
return 1;
}
+ uint32_t divu = Divu(2264, 31);
+ if (divu != 73) {
+ fprintf(stderr, "ERROR: Divu(2264, 31)=%d, want %d\n", divu, 73);
+ return 1;
+ }
// test.bash looks for "PASS" to ensure this program has reached the end.
printf("PASS\n");
return 0;
diff --git a/libgo/misc/cgo/testcshared/src/p/p.go b/libgo/misc/cgo/testcshared/src/p/p.go
index 82b445c..0f02cf3 100644
--- a/libgo/misc/cgo/testcshared/src/p/p.go
+++ b/libgo/misc/cgo/testcshared/src/p/p.go
@@ -8,3 +8,6 @@ import "C"
//export FromPkg
func FromPkg() int32 { return 1024 }
+
+//export Divu
+func Divu(a, b uint32) uint32 { return a / b }
diff --git a/libgo/misc/cgo/testcshared/test.bash b/libgo/misc/cgo/testcshared/test.bash
index 0315fb0..315a0d4 100644
--- a/libgo/misc/cgo/testcshared/test.bash
+++ b/libgo/misc/cgo/testcshared/test.bash
@@ -27,7 +27,7 @@ fi
# Directory where cgo headers and outputs will be installed.
# The installation directory format varies depending on the platform.
installdir=pkg/${goos}_${goarch}_testcshared_shared
-if [ "${goos}" == "darwin" ]; then
+if [ "${goos}" = "darwin" ]; then
installdir=pkg/${goos}_${goarch}_testcshared
fi
@@ -40,13 +40,13 @@ function cleanup() {
rm -f testp testp2 testp3 testp4 testp5
rm -rf pkg "${goroot}/${installdir}"
- if [ "$goos" == "android" ]; then
+ if [ "$goos" = "android" ]; then
adb shell rm -rf "$androidpath"
fi
}
trap cleanup EXIT
-if [ "$goos" == "android" ]; then
+if [ "$goos" = "android" ]; then
adb shell mkdir -p "$androidpath"
fi
@@ -69,7 +69,7 @@ function run() {
function binpush() {
bin=${1}
- if [ "$goos" == "android" ]; then
+ if [ "$goos" = "android" ]; then
adb push "$bin" "${androidpath}/${bin}" 2>/dev/null
fi
}
@@ -79,7 +79,7 @@ rm -rf pkg
suffix="-installsuffix testcshared"
libext="so"
-if [ "$goos" == "darwin" ]; then
+if [ "$goos" = "darwin" ]; then
libext="dylib"
fi
@@ -89,7 +89,7 @@ GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
binpush libgo.$libext
-if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+if [ "$goos" = "linux" ] || [ "$goos" = "android" ] ; then
if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
echo "libgo.$libext has TEXTREL set"
exit 1
@@ -97,8 +97,8 @@ if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
fi
GOGCCFLAGS=$(go env GOGCCFLAGS)
-if [ "$goos" == "android" ]; then
- GOGCCFLAGS="${GOGCCFLAGS} -pie"
+if [ "$goos" = "android" ]; then
+ GOGCCFLAGS="${GOGCCFLAGS} -pie -fuse-ld=gold"
fi
status=0
@@ -127,7 +127,7 @@ fi
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
binpush libgo2.$libext
linkflags="-Wl,--no-as-needed"
-if [ "$goos" == "darwin" ]; then
+if [ "$goos" = "darwin" ]; then
linkflags=""
fi
$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
@@ -139,7 +139,7 @@ if [ "$output" != "PASS" ]; then
fi
# test3: tests main.main is exported on android.
-if [ "$goos" == "android" ]; then
+if [ "$goos" = "android" ]; then
$(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
binpush testp3
output=$(run ./testp ./libgo.so)
diff --git a/libgo/misc/cgo/testplugin/src/issue19534/main.go b/libgo/misc/cgo/testplugin/src/issue19534/main.go
new file mode 100644
index 0000000..de263b6
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/issue19534/main.go
@@ -0,0 +1,23 @@
+// Copyright 2017 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
+
+import "plugin"
+
+func main() {
+ p, err := plugin.Open("plugin.so")
+ if err != nil {
+ panic(err)
+ }
+
+ sym, err := p.Lookup("Foo")
+ if err != nil {
+ panic(err)
+ }
+ f := sym.(func() int)
+ if f() != 42 {
+ panic("expected f() == 42")
+ }
+}
diff --git a/libgo/misc/cgo/testplugin/src/issue19534/plugin.go b/libgo/misc/cgo/testplugin/src/issue19534/plugin.go
new file mode 100644
index 0000000..582d333
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/issue19534/plugin.go
@@ -0,0 +1,9 @@
+// Copyright 2017 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
+
+func Foo() int {
+ return 42
+}
diff --git a/libgo/misc/cgo/testplugin/test.bash b/libgo/misc/cgo/testplugin/test.bash
index ab7430a..69df5bd 100644
--- a/libgo/misc/cgo/testplugin/test.bash
+++ b/libgo/misc/cgo/testplugin/test.bash
@@ -16,7 +16,7 @@ goarch=$(go env GOARCH)
function cleanup() {
rm -f plugin*.so unnamed*.so iface*.so
- rm -rf host pkg sub iface issue18676
+ rm -rf host pkg sub iface issue18676 issue19534
}
trap cleanup EXIT
@@ -44,3 +44,9 @@ LD_LIBRARY_PATH=$(pwd) ./iface
GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
timeout 10s ./issue18676
+
+# Test for issue 19534 - that we can load a plugin built in a path with non-alpha
+# characters
+GOPATH=$(pwd) go build -buildmode=plugin -ldflags='-pluginpath=issue.19534' -o plugin.so src/issue19534/plugin.go
+GOPATH=$(pwd) go build -o issue19534 src/issue19534/main.go
+./issue19534
diff --git a/libgo/misc/cgo/testplugin/unnamed1.go b/libgo/misc/cgo/testplugin/unnamed1.go
index 102edaf..5c1df08 100644
--- a/libgo/misc/cgo/testplugin/unnamed1.go
+++ b/libgo/misc/cgo/testplugin/unnamed1.go
@@ -9,4 +9,15 @@ import "C"
func FuncInt() int { return 1 }
+// Add a recursive type to to check that type equality across plugins doesn't
+// crash. See https://golang.org/issues/19258
+func FuncRecursive() X { return X{} }
+
+type Y struct {
+ X *X
+}
+type X struct {
+ Y Y
+}
+
func main() {}
diff --git a/libgo/misc/cgo/testplugin/unnamed2.go b/libgo/misc/cgo/testplugin/unnamed2.go
index 55070d5..7ef6610 100644
--- a/libgo/misc/cgo/testplugin/unnamed2.go
+++ b/libgo/misc/cgo/testplugin/unnamed2.go
@@ -9,4 +9,13 @@ import "C"
func FuncInt() int { return 2 }
+func FuncRecursive() X { return X{} }
+
+type Y struct {
+ X *X
+}
+type X struct {
+ Y Y
+}
+
func main() {}
diff --git a/libgo/misc/cgo/testsanitizers/test.bash b/libgo/misc/cgo/testsanitizers/test.bash
index 4da8502..9f80af6 100644
--- a/libgo/misc/cgo/testsanitizers/test.bash
+++ b/libgo/misc/cgo/testsanitizers/test.bash
@@ -72,12 +72,12 @@ testmsanshared() {
goos=$(go env GOOS)
suffix="-installsuffix testsanitizers"
libext="so"
- if [ "$goos" == "darwin" ]; then
+ if [ "$goos" = "darwin" ]; then
libext="dylib"
fi
go build -msan -buildmode=c-shared $suffix -o ${TMPDIR}/libmsanshared.$libext msan_shared.go
- echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
+ echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
$CC $(go env GOGCCFLAGS) -fsanitize=memory -o ${TMPDIR}/testmsanshared ${TMPDIR}/testmsanshared.c ${TMPDIR}/libmsanshared.$libext
if ! LD_LIBRARY_PATH=. ${TMPDIR}/testmsanshared; then
@@ -131,21 +131,43 @@ if test "$msan" = "yes"; then
testmsanshared
fi
+testtsanshared() {
+ goos=$(go env GOOS)
+ suffix="-installsuffix tsan"
+ libext="so"
+ if [ "$goos" = "darwin" ]; then
+ libext="dylib"
+ fi
+ go build -buildmode=c-shared $suffix -o ${TMPDIR}/libtsanshared.$libext tsan_shared.go
+
+ echo 'int main() { return 0; }' > ${TMPDIR}/testtsanshared.c
+ $CC $(go env GOGCCFLAGS) -fsanitize=thread -o ${TMPDIR}/testtsanshared ${TMPDIR}/testtsanshared.c ${TMPDIR}/libtsanshared.$libext
+
+ if ! LD_LIBRARY_PATH=. ${TMPDIR}/testtsanshared; then
+ echo "FAIL: tsan_shared"
+ status=1
+ fi
+ rm -f ${TMPDIR}/{testtsanshared,testtsanshared.c,libtsanshared.$libext}
+}
+
if test "$tsan" = "yes"; then
echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
ok=yes
if ! $CC -fsanitize=thread ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$ &> ${TMPDIR}/testsanitizers$$.err; then
ok=no
fi
- if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then
+ if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then
echo "skipping tsan tests: -fsanitize=thread not supported"
tsan=no
- elif test "$ok" != "yes"; then
- cat ${TMPDIR}/testsanitizers$$.err
- echo "skipping tsan tests: -fsanitizer=thread build failed"
- tsan=no
- fi
- rm -f ${TMPDIR}/testsanitizers$$*
+ elif test "$ok" != "yes"; then
+ cat ${TMPDIR}/testsanitizers$$.err
+ echo "skipping tsan tests: -fsanitizer=thread build failed"
+ tsan=no
+ elif ! ${TMPDIR}/testsanitizers$$ 2>&1; then
+ echo "skipping tsan tests: running tsan program failed"
+ tsan=no
+ fi
+ rm -f ${TMPDIR}/testsanitizers$$*
fi
# Run a TSAN test.
@@ -177,8 +199,10 @@ if test "$tsan" = "yes"; then
# These tests are only reliable using clang or GCC version 7 or later.
# Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
ok=false
+ clang=false
if ${CC} --version | grep clang >/dev/null 2>&1; then
ok=true
+ clang=true
else
ver=$($CC -dumpversion)
major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
@@ -190,14 +214,19 @@ if test "$tsan" = "yes"; then
fi
if test "$ok" = "true"; then
- # This test requires rebuilding os/user with -fsanitize=thread.
+ # These tests require rebuilding os/user with -fsanitize=thread.
testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
-
- # This test requires rebuilding runtime/cgo with -fsanitize=thread.
testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
-
- # This test requires rebuilding runtime/cgo with -fsanitize=thread.
testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+
+ # The remaining tests reportedly hang when built with GCC; issue #21196.
+ if test "$clang" = "true"; then
+ testtsan tsan10.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+ testtsan tsan11.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+ testtsan tsan12.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+ fi
+
+ testtsanshared
fi
fi
diff --git a/libgo/misc/cgo/testsanitizers/tsan10.go b/libgo/misc/cgo/testsanitizers/tsan10.go
new file mode 100644
index 0000000..a40f245
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan10.go
@@ -0,0 +1,31 @@
+// Copyright 2017 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 hung when run under the C/C++ ThreadSanitizer.
+// TSAN defers asynchronous signals until the signaled thread calls into libc.
+// Since the Go runtime makes direct futex syscalls, Go runtime threads could
+// run for an arbitrarily long time without triggering the libc interceptors.
+// See https://golang.org/issue/18717.
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+/*
+#cgo CFLAGS: -g -fsanitize=thread
+#cgo LDFLAGS: -g -fsanitize=thread
+*/
+import "C"
+
+func main() {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, syscall.SIGUSR1)
+ defer signal.Stop(c)
+ syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+ <-c
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan11.go b/libgo/misc/cgo/testsanitizers/tsan11.go
new file mode 100644
index 0000000..70ac9c8
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan11.go
@@ -0,0 +1,55 @@
+// Copyright 2017 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 hung when run under the C/C++ ThreadSanitizer. TSAN defers
+// asynchronous signals until the signaled thread calls into libc. The runtime's
+// sysmon goroutine idles itself using direct usleep syscalls, so it could
+// run for an arbitrarily long time without triggering the libc interceptors.
+// See https://golang.org/issue/18717.
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+/*
+#cgo CFLAGS: -g -fsanitize=thread
+#cgo LDFLAGS: -g -fsanitize=thread
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void raise_usr2(int signo) {
+ raise(SIGUSR2);
+}
+
+static void register_handler(int signo) {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = raise_usr2;
+
+ if (sigaction(SIGUSR1, &sa, NULL) != 0) {
+ perror("failed to register SIGUSR1 handler");
+ exit(EXIT_FAILURE);
+ }
+}
+*/
+import "C"
+
+func main() {
+ ch := make(chan os.Signal)
+ signal.Notify(ch, syscall.SIGUSR2)
+
+ C.register_handler(C.int(syscall.SIGUSR1))
+ syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+
+ <-ch
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan12.go b/libgo/misc/cgo/testsanitizers/tsan12.go
new file mode 100644
index 0000000..3e767ee
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan12.go
@@ -0,0 +1,35 @@
+// Copyright 2017 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 hung when run under the C/C++ ThreadSanitizer. TSAN installs a
+// libc interceptor that writes signal handlers to a global variable within the
+// TSAN runtime instead of making a sigaction system call. A bug in
+// syscall.runtime_AfterForkInChild corrupted TSAN's signal forwarding table
+// during calls to (*os/exec.Cmd).Run, causing the parent process to fail to
+// invoke signal handlers.
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "os/signal"
+ "syscall"
+)
+
+import "C"
+
+func main() {
+ ch := make(chan os.Signal)
+ signal.Notify(ch, syscall.SIGUSR1)
+
+ if err := exec.Command("true").Run(); err != nil {
+ fmt.Fprintf(os.Stderr, "Unexpected error from `true`: %v", err)
+ os.Exit(1)
+ }
+
+ syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+ <-ch
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan_shared.go b/libgo/misc/cgo/testsanitizers/tsan_shared.go
new file mode 100644
index 0000000..55ff67e
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan_shared.go
@@ -0,0 +1,63 @@
+// Copyright 2017 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 with SIGSEGV when run under the C/C++ ThreadSanitizer.
+// The Go runtime had re-registered the C handler with the wrong flags due to a
+// typo, resulting in null pointers being passed for the info and context
+// parameters to the handler.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+
+void check_params(int signo, siginfo_t *info, void *context) {
+ ucontext_t* uc = (ucontext_t*)(context);
+
+ if (info->si_signo != signo) {
+ fprintf(stderr, "info->si_signo does not match signo.\n");
+ abort();
+ }
+
+ if (uc->uc_stack.ss_size == 0) {
+ fprintf(stderr, "uc_stack has size 0.\n");
+ abort();
+ }
+}
+
+
+// Set up the signal handler in a high priority constructor, so
+// that it is installed before the Go code starts.
+
+static void register_handler(void) __attribute__ ((constructor (200)));
+
+static void register_handler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = check_params;
+
+ if (sigaction(SIGUSR1, &sa, NULL) != 0) {
+ perror("failed to register SIGUSR1 handler");
+ exit(EXIT_FAILURE);
+ }
+}
+*/
+import "C"
+
+import "syscall"
+
+func init() {
+ C.raise(C.int(syscall.SIGUSR1))
+}
+
+func main() {}
diff --git a/libgo/misc/cgo/testshared/shared_test.go b/libgo/misc/cgo/testshared/shared_test.go
index f0766e5..9e682a2 100644
--- a/libgo/misc/cgo/testshared/shared_test.go
+++ b/libgo/misc/cgo/testshared/shared_test.go
@@ -10,7 +10,6 @@ import (
"debug/elf"
"encoding/binary"
"errors"
- "flag"
"fmt"
"go/build"
"io"
@@ -166,7 +165,6 @@ func TestMain(m *testing.M) {
// That won't work if GOBIN is set.
os.Unsetenv("GOBIN")
- flag.Parse()
exitCode, err := testMain(m)
if err != nil {
log.Fatal(err)
@@ -402,6 +400,12 @@ func TestTrivialExecutablePIE(t *testing.T) {
AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
}
+// Build a division test program and check it runs.
+func TestDivisionExecutable(t *testing.T) {
+ goCmd(t, "install", "-linkshared", "division")
+ run(t, "division executable", "./bin/division")
+}
+
// Build an executable that uses cgo linked against the shared runtime and check it
// runs.
func TestCgoExecutable(t *testing.T) {
@@ -759,6 +763,13 @@ func appendFile(path, content string) {
}
}
+func writeFile(path, content string) {
+ err := ioutil.WriteFile(path, []byte(content), 0644)
+ if err != nil {
+ log.Fatalf("ioutil.WriteFile failed: %v", err)
+ }
+}
+
func TestABIChecking(t *testing.T) {
goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
goCmd(t, "install", "-linkshared", "exe")
@@ -797,9 +808,10 @@ func TestABIChecking(t *testing.T) {
run(t, "rebuilt exe", "./bin/exe")
// If we make a change which does not break ABI (such as adding an unexported
- // function) and rebuild libdepBase.so, exe still works.
+ // function) and rebuild libdepBase.so, exe still works, even if new function
+ // is in a file by itself.
resetFileStamps()
- appendFile("src/depBase/dep.go", "func noABIBreak() {}\n")
+ writeFile("src/depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n")
goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
run(t, "after non-ABI breaking change", "./bin/exe")
}
diff --git a/libgo/misc/cgo/testshared/src/division/division.go b/libgo/misc/cgo/testshared/src/division/division.go
new file mode 100644
index 0000000..bb5fc98
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/division/division.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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
+
+//go:noinline
+func div(x, y uint32) uint32 {
+ return x / y
+}
+
+func main() {
+ a := div(97, 11)
+ if a != 8 {
+ panic("FAIL")
+ }
+}