summaryrefslogtreecommitdiffstats
path: root/misc/cgo/testcshared/testdata
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 /misc/cgo/testcshared/testdata
parentInitial commit. (diff)
downloadgolang-1.16-upstream.tar.xz
golang-1.16-upstream.zip
Adding upstream version 1.16.10.upstream/1.16.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--misc/cgo/testcshared/testdata/go2c2go/go/shlib.go12
-rw-r--r--misc/cgo/testcshared/testdata/go2c2go/m1/c.c9
-rw-r--r--misc/cgo/testcshared/testdata/go2c2go/m1/main.go22
-rw-r--r--misc/cgo/testcshared/testdata/go2c2go/m2/main.go22
-rw-r--r--misc/cgo/testcshared/testdata/libgo/libgo.go46
-rw-r--r--misc/cgo/testcshared/testdata/libgo2/dup2.go13
-rw-r--r--misc/cgo/testcshared/testdata/libgo2/dup3.go13
-rw-r--r--misc/cgo/testcshared/testdata/libgo2/libgo2.go52
-rw-r--r--misc/cgo/testcshared/testdata/libgo4/libgo4.go45
-rw-r--r--misc/cgo/testcshared/testdata/libgo5/libgo5.go44
-rw-r--r--misc/cgo/testcshared/testdata/main0.c42
-rw-r--r--misc/cgo/testcshared/testdata/main1.c69
-rw-r--r--misc/cgo/testcshared/testdata/main2.c56
-rw-r--r--misc/cgo/testcshared/testdata/main3.c29
-rw-r--r--misc/cgo/testcshared/testdata/main4.c215
-rw-r--r--misc/cgo/testcshared/testdata/main5.c199
-rw-r--r--misc/cgo/testcshared/testdata/p/p.go13
17 files changed, 901 insertions, 0 deletions
diff --git a/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go b/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go
new file mode 100644
index 0000000..76a5323
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go
@@ -0,0 +1,12 @@
+// Copyright 2018 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 "C"
+
+//export GoFunc
+func GoFunc() int { return 1 }
+
+func main() {}
diff --git a/misc/cgo/testcshared/testdata/go2c2go/m1/c.c b/misc/cgo/testcshared/testdata/go2c2go/m1/c.c
new file mode 100644
index 0000000..0e8fac4
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/go2c2go/m1/c.c
@@ -0,0 +1,9 @@
+// Copyright 2018 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.
+
+#include "libtestgo2c2go.h"
+
+int CFunc(void) {
+ return (GoFunc() << 8) + 2;
+}
diff --git a/misc/cgo/testcshared/testdata/go2c2go/m1/main.go b/misc/cgo/testcshared/testdata/go2c2go/m1/main.go
new file mode 100644
index 0000000..17ba1eb
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/go2c2go/m1/main.go
@@ -0,0 +1,22 @@
+// Copyright 2018 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
+
+// extern int CFunc(void);
+import "C"
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ got := C.CFunc()
+ const want = (1 << 8) | 2
+ if got != want {
+ fmt.Printf("got %#x, want %#x\n", got, want)
+ os.Exit(1)
+ }
+}
diff --git a/misc/cgo/testcshared/testdata/go2c2go/m2/main.go b/misc/cgo/testcshared/testdata/go2c2go/m2/main.go
new file mode 100644
index 0000000..91bf308
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/go2c2go/m2/main.go
@@ -0,0 +1,22 @@
+// Copyright 2018 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
+
+// #include "libtestgo2c2go.h"
+import "C"
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ got := C.GoFunc()
+ const want = 1
+ if got != want {
+ fmt.Printf("got %#x, want %#x\n", got, want)
+ os.Exit(1)
+ }
+}
diff --git a/misc/cgo/testcshared/testdata/libgo/libgo.go b/misc/cgo/testcshared/testdata/libgo/libgo.go
new file mode 100644
index 0000000..0634417
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo/libgo.go
@@ -0,0 +1,46 @@
+// 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.
+
+package main
+
+import (
+ "syscall"
+ _ "testcshared/p"
+ "time"
+)
+
+import "C"
+
+var initCh = make(chan int, 1)
+var ranMain bool
+
+func init() {
+ // emulate an exceedingly slow package initialization function
+ time.Sleep(100 * time.Millisecond)
+ initCh <- 42
+}
+
+func main() {
+ ranMain = true
+}
+
+//export DidInitRun
+func DidInitRun() bool {
+ select {
+ case x := <-initCh:
+ if x != 42 {
+ // Just in case initCh was not correctly made.
+ println("want init value of 42, got: ", x)
+ syscall.Exit(2)
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+//export DidMainRun
+func DidMainRun() bool {
+ return ranMain
+}
diff --git a/misc/cgo/testcshared/testdata/libgo2/dup2.go b/misc/cgo/testcshared/testdata/libgo2/dup2.go
new file mode 100644
index 0000000..d18f0b1
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo2/dup2.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux,!arm64 netbsd openbsd
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup2(oldfd, newfd)
+}
diff --git a/misc/cgo/testcshared/testdata/libgo2/dup3.go b/misc/cgo/testcshared/testdata/libgo2/dup3.go
new file mode 100644
index 0000000..c9c65a6
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo2/dup3.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build linux,arm64
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup3(oldfd, newfd, 0)
+}
diff --git a/misc/cgo/testcshared/testdata/libgo2/libgo2.go b/misc/cgo/testcshared/testdata/libgo2/libgo2.go
new file mode 100644
index 0000000..e57c93b
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo2/libgo2.go
@@ -0,0 +1,52 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main
+
+// Test a shared library created by -buildmode=c-shared that does not
+// export anything.
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+)
+
+// To test this we want to communicate between the main program and
+// the shared library without using any exported symbols. The init
+// function creates a pipe and Dups the read end to a known number
+// that the C code can also use.
+
+const (
+ fd = 30
+)
+
+func init() {
+ var p [2]int
+ if e := syscall.Pipe(p[0:]); e != nil {
+ fmt.Fprintf(os.Stderr, "pipe: %v\n", e)
+ os.Exit(2)
+ }
+
+ if e := dup2(p[0], fd); e != nil {
+ fmt.Fprintf(os.Stderr, "dup2: %v\n", e)
+ os.Exit(2)
+ }
+
+ const str = "PASS"
+ if n, e := syscall.Write(p[1], []byte(str)); e != nil || n != len(str) {
+ fmt.Fprintf(os.Stderr, "write: %d %v\n", n, e)
+ os.Exit(2)
+ }
+
+ if e := syscall.Close(p[1]); e != nil {
+ fmt.Fprintf(os.Stderr, "close: %v\n", e)
+ os.Exit(2)
+ }
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcshared/testdata/libgo4/libgo4.go b/misc/cgo/testcshared/testdata/libgo4/libgo4.go
new file mode 100644
index 0000000..ab40b75
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo4/libgo4.go
@@ -0,0 +1,45 @@
+// 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.
+
+package main
+
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+ for i := 0; i < 4; i++ {
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ }
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+ defer func() {
+ if recover() == nil {
+ fmt.Fprintln(os.Stderr, "no panic from segv")
+ os.Exit(1)
+ }
+ }()
+ *P = 0
+ fmt.Fprintln(os.Stderr, "continued after segv")
+ os.Exit(1)
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcshared/testdata/libgo5/libgo5.go b/misc/cgo/testcshared/testdata/libgo5/libgo5.go
new file mode 100644
index 0000000..94e5d21
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/libgo5/libgo5.go
@@ -0,0 +1,44 @@
+// 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.
+
+package main
+
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+ sigioChan = make(chan os.Signal, 1)
+ signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+ signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+ select {
+ case <-sigioChan:
+ return 1
+ case <-time.After(100 * time.Millisecond):
+ return 0
+ }
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcshared/testdata/main0.c b/misc/cgo/testcshared/testdata/main0.c
new file mode 100644
index 0000000..39ef7e3
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main0.c
@@ -0,0 +1,42 @@
+// 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.
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "p.h"
+#include "libgo.h"
+
+// Tests libgo.so to export the following functions.
+// 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) {
+ fprintf(stderr, "ERROR: DidInitRun returned unexpected results: %d\n",
+ ran_init);
+ return 1;
+ }
+ int8_t ran_main = DidMainRun();
+ if (ran_main) {
+ fprintf(stderr, "ERROR: DidMainRun returned unexpected results: %d\n",
+ ran_main);
+ return 1;
+ }
+ int32_t from_pkg = FromPkg();
+ if (from_pkg != 1024) {
+ 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/misc/cgo/testcshared/testdata/main1.c b/misc/cgo/testcshared/testdata/main1.c
new file mode 100644
index 0000000..420dd1e
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main1.c
@@ -0,0 +1,69 @@
+// 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+int check_int8(void* handle, const char* fname, int8_t want) {
+ int8_t (*fn)();
+ fn = (int8_t (*)())dlsym(handle, fname);
+ if (!fn) {
+ fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+ return 1;
+ }
+ signed char ret = fn();
+ if (ret != want) {
+ fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+ return 1;
+ }
+ return 0;
+}
+
+int check_int32(void* handle, const char* fname, int32_t want) {
+ int32_t (*fn)();
+ fn = (int32_t (*)())dlsym(handle, fname);
+ if (!fn) {
+ fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+ return 1;
+ }
+ int32_t ret = fn();
+ if (ret != want) {
+ fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+ return 1;
+ }
+ return 0;
+}
+
+// Tests libgo.so to export the following functions.
+// int8_t DidInitRun() // returns true
+// int8_t DidMainRun() // returns true
+// int32_t FromPkg() // returns 1024
+int main(int argc, char** argv) {
+ void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+ dlerror());
+ return 2;
+ }
+
+ int ret = 0;
+ ret = check_int8(handle, "DidInitRun", 1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = check_int8(handle, "DidMainRun", 0);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = check_int32(handle, "FromPkg", 1024);
+ if (ret != 0) {
+ return ret;
+ }
+ // test.bash looks for "PASS" to ensure this program has reached the end.
+ printf("PASS\n");
+ return 0;
+}
diff --git a/misc/cgo/testcshared/testdata/main2.c b/misc/cgo/testcshared/testdata/main2.c
new file mode 100644
index 0000000..f89bcca
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main2.c
@@ -0,0 +1,56 @@
+// 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.
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define fd (30)
+
+// Tests libgo2.so, which does not export any functions.
+// Read a string from the file descriptor and print it.
+int main(void) {
+ int i;
+ ssize_t n;
+ char buf[20];
+ struct timespec ts;
+
+ // The descriptor will be initialized in a thread, so we have to
+ // give a chance to get opened.
+ for (i = 0; i < 200; i++) {
+ n = read(fd, buf, sizeof buf);
+ if (n >= 0)
+ break;
+ if (errno != EBADF && errno != EINVAL) {
+ fprintf(stderr, "BUG: read: %s\n", strerror(errno));
+ return 2;
+ }
+
+ // An EBADF error means that the shared library has not opened the
+ // descriptor yet.
+ ts.tv_sec = 0;
+ ts.tv_nsec = 10000000;
+ nanosleep(&ts, NULL);
+ }
+
+ if (n < 0) {
+ fprintf(stderr, "BUG: failed to read any data from pipe\n");
+ return 2;
+ }
+
+ if (n == 0) {
+ fprintf(stderr, "BUG: unexpected EOF\n");
+ return 2;
+ }
+
+ if (n == sizeof buf) {
+ n--;
+ }
+ buf[n] = '\0';
+ printf("%s\n", buf);
+ return 0;
+}
diff --git a/misc/cgo/testcshared/testdata/main3.c b/misc/cgo/testcshared/testdata/main3.c
new file mode 100644
index 0000000..49cc055
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main3.c
@@ -0,0 +1,29 @@
+// 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+// Tests "main.main" is exported on android/arm,
+// which golang.org/x/mobile/app depends on.
+int main(int argc, char** argv) {
+ void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+ dlerror());
+ return 2;
+ }
+
+ uintptr_t main_fn = (uintptr_t)dlsym(handle, "main.main");
+ if (!main_fn) {
+ fprintf(stderr, "ERROR: missing main.main: %s\n", dlerror());
+ return 2;
+ }
+
+ // TODO(hyangah): check that main.main can run.
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/misc/cgo/testcshared/testdata/main4.c b/misc/cgo/testcshared/testdata/main4.c
new file mode 100644
index 0000000..355cdef
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main4.c
@@ -0,0 +1,215 @@
+// 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.
+
+// Test that a signal handler that uses up stack space does not crash
+// if the signal is delivered to a thread running a goroutine.
+// This is a lot like misc/cgo/testcarchive/main2.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+ char a[1024];
+
+ *p = '\0';
+ if (i > 0) {
+ recur(i - 1, a);
+ }
+}
+
+// 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];
+
+ recur(4, a);
+ sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigset_t mask;
+ int i;
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGSEGV) < 0) {
+ die("sigaddset");
+ }
+ i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ // Don't try this at home.
+ longjmp(jmp, signo);
+
+ // We should never get here.
+ abort();
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ struct sigaction sa;
+ void* handle;
+ void (*fn)(void);
+ sigset_t mask;
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 2;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Call setsid so that we can use kill(0, SIGIO) below.
+ // Don't check the return value so that this works both from
+ // a job control shell and from a shell script.
+ setsid();
+
+ if (verbose) {
+ printf("calling sigaction\n");
+ }
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ sa.sa_sigaction = segvHandler;
+ if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ if (verbose) {
+ printf("calling dlopen\n");
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Start some goroutines.
+ fn = (void(*)(void))dlsym(handle, "RunGoroutines");
+ if (fn == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling RunGoroutines\n");
+ }
+
+ fn();
+
+ // Block SIGIO in this thread to make it more likely that it
+ // will be delivered to a goroutine.
+
+ if (verbose) {
+ printf("calling pthread_sigmask\n");
+ }
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGIO) < 0) {
+ die("sigaddset");
+ }
+ i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling kill\n");
+ }
+
+ if (kill(0, SIGIO) < 0) {
+ die("kill");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (verbose) {
+ printf("calling setjmp\n");
+ }
+
+ // Test that a SIGSEGV on this thread is delivered to us.
+ if (setjmp(jmp) == 0) {
+ if (verbose) {
+ printf("triggering SIGSEGV\n");
+ }
+
+ *nullPointer = '\0';
+
+ fprintf(stderr, "continued after address error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Make sure that a SIGSEGV in Go causes a run-time panic.
+ fn = (void (*)(void))dlsym(handle, "TestSEGV");
+ if (fn == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling TestSEGV\n");
+ }
+
+ fn();
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/misc/cgo/testcshared/testdata/main5.c b/misc/cgo/testcshared/testdata/main5.c
new file mode 100644
index 0000000..1bc9910
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/main5.c
@@ -0,0 +1,199 @@
+// 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.
+
+// Test that a signal handler works in non-Go code when using
+// os/signal.Notify.
+// This is a lot like misc/cgo/testcarchive/main3.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ struct sigaction sa;
+ void* handle;
+ void (*fn1)(void);
+ int (*sawSIGIO)(void);
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 2;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (verbose) {
+ printf("calling sigaction\n");
+ }
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ if (verbose) {
+ printf("calling dlopen\n");
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ // At this point there should not be a Go signal handler
+ // installed for SIGIO.
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ sigioSeen = 0;
+
+ // Tell the Go code to catch SIGIO.
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO");
+ if (fn1 == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling CatchSIGIO\n");
+ }
+
+ fn1();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Check that the Go code saw SIGIO.
+ sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO");
+ if (sawSIGIO == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (!sawSIGIO()) {
+ fprintf(stderr, "Go handler did not see SIGIO\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (sigioSeen != 0) {
+ fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Tell the Go code to stop catching SIGIO.
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO");
+ if (fn1 == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling ResetSIGIO\n");
+ }
+
+ fn1();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (sawSIGIO()) {
+ fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/misc/cgo/testcshared/testdata/p/p.go b/misc/cgo/testcshared/testdata/p/p.go
new file mode 100644
index 0000000..0f02cf3
--- /dev/null
+++ b/misc/cgo/testcshared/testdata/p/p.go
@@ -0,0 +1,13 @@
+// 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.
+
+package p
+
+import "C"
+
+//export FromPkg
+func FromPkg() int32 { return 1024 }
+
+//export Divu
+func Divu(a, b uint32) uint32 { return a / b }