Initial commit: Go 1.23 release state
This commit is contained in:
1383
src/cmd/cgo/internal/testcarchive/carchive_test.go
Normal file
1383
src/cmd/cgo/internal/testcarchive/carchive_test.go
Normal file
File diff suppressed because it is too large
Load Diff
53
src/cmd/cgo/internal/testcarchive/testdata/libgo/libgo.go
vendored
Normal file
53
src/cmd/cgo/internal/testcarchive/testdata/libgo/libgo.go
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "testcarchive/p"
|
||||
)
|
||||
|
||||
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 }
|
||||
|
||||
//export CheckArgs
|
||||
func CheckArgs() {
|
||||
if len(os.Args) != 3 || os.Args[1] != "arg1" || os.Args[2] != "arg2" {
|
||||
fmt.Printf("CheckArgs: want [_, arg1, arg2], got: %v\n", os.Args)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
91
src/cmd/cgo/internal/testcarchive/testdata/libgo2/libgo2.go
vendored
Normal file
91
src/cmd/cgo/internal/testcarchive/testdata/libgo2/libgo2.go
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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
|
||||
|
||||
/*
|
||||
#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 (
|
||||
"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 {}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// Block blocks the current thread while running Go code.
|
||||
//
|
||||
//export Block
|
||||
func Block() {
|
||||
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)
|
||||
}
|
||||
|
||||
// Noop ensures that the Go runtime is initialized.
|
||||
//
|
||||
//export Noop
|
||||
func Noop() {
|
||||
}
|
||||
|
||||
// Raise SIGPIPE.
|
||||
//
|
||||
//export GoRaiseSIGPIPE
|
||||
func GoRaiseSIGPIPE() {
|
||||
C.CRaiseSIGPIPE()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
60
src/cmd/cgo/internal/testcarchive/testdata/libgo3/libgo3.go
vendored
Normal file
60
src/cmd/cgo/internal/testcarchive/testdata/libgo3/libgo3.go
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 reports whether we saw a SIGIO.
|
||||
//
|
||||
//export SawSIGIO
|
||||
func SawSIGIO() C.int {
|
||||
select {
|
||||
case <-sigioChan:
|
||||
return 1
|
||||
case <-time.After(5 * time.Second):
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// 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() {
|
||||
}
|
||||
55
src/cmd/cgo/internal/testcarchive/testdata/libgo4/libgo4.go
vendored
Normal file
55
src/cmd/cgo/internal/testcarchive/testdata/libgo4/libgo4.go
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// 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
|
||||
|
||||
/*
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// Raise SIGIO.
|
||||
static void CRaiseSIGIO(pthread_t* p) {
|
||||
pthread_kill(*p, SIGIO);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var sigioCount int32
|
||||
|
||||
// Catch SIGIO.
|
||||
//
|
||||
//export GoCatchSIGIO
|
||||
func GoCatchSIGIO() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGIO)
|
||||
go func() {
|
||||
for range c {
|
||||
atomic.AddInt32(&sigioCount, 1)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Raise SIGIO.
|
||||
//
|
||||
//export GoRaiseSIGIO
|
||||
func GoRaiseSIGIO(p *C.pthread_t) {
|
||||
C.CRaiseSIGIO(p)
|
||||
}
|
||||
|
||||
// Return the number of SIGIO signals seen.
|
||||
//
|
||||
//export SIGIOCount
|
||||
func SIGIOCount() C.int {
|
||||
return C.int(atomic.LoadInt32(&sigioCount))
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
25
src/cmd/cgo/internal/testcarchive/testdata/libgo6/sigprof.go
vendored
Normal file
25
src/cmd/cgo/internal/testcarchive/testdata/libgo6/sigprof.go
vendored
Normal file
@@ -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"
|
||||
"runtime/pprof"
|
||||
)
|
||||
|
||||
import "C"
|
||||
|
||||
//export go_start_profile
|
||||
func go_start_profile() {
|
||||
pprof.StartCPUProfile(io.Discard)
|
||||
}
|
||||
|
||||
//export go_stop_profile
|
||||
func go_stop_profile() {
|
||||
pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
17
src/cmd/cgo/internal/testcarchive/testdata/libgo7/sink.go
vendored
Normal file
17
src/cmd/cgo/internal/testcarchive/testdata/libgo7/sink.go
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019 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"
|
||||
|
||||
var sink []byte
|
||||
|
||||
//export GoFunction7
|
||||
func GoFunction7() {
|
||||
sink = make([]byte, 4096)
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
36
src/cmd/cgo/internal/testcarchive/testdata/libgo8/a.go
vendored
Normal file
36
src/cmd/cgo/internal/testcarchive/testdata/libgo8/a.go
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2021 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"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var started int32
|
||||
|
||||
// Start a goroutine that loops forever.
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(1)
|
||||
go func() {
|
||||
for {
|
||||
atomic.StoreInt32(&started, 1)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
//export GoFunction8
|
||||
func GoFunction8() {
|
||||
for atomic.LoadInt32(&started) == 0 {
|
||||
runtime.Gosched()
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
14
src/cmd/cgo/internal/testcarchive/testdata/libgo9/a.go
vendored
Normal file
14
src/cmd/cgo/internal/testcarchive/testdata/libgo9/a.go
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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
|
||||
|
||||
import "runtime"
|
||||
|
||||
import "C"
|
||||
|
||||
func main() {}
|
||||
|
||||
//export GoF
|
||||
func GoF() { runtime.GC() }
|
||||
48
src/cmd/cgo/internal/testcarchive/testdata/main.c
vendored
Normal file
48
src/cmd/cgo/internal/testcarchive/testdata/main.c
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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 <string.h>
|
||||
|
||||
#include "p.h"
|
||||
#include "libgo.h"
|
||||
|
||||
extern int install_handler();
|
||||
extern int check_handler();
|
||||
|
||||
int main(void) {
|
||||
int32_t res;
|
||||
|
||||
int r1 = install_handler();
|
||||
if (r1!=0) {
|
||||
return r1;
|
||||
}
|
||||
|
||||
if (!DidInitRun()) {
|
||||
fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (DidMainRun()) {
|
||||
fprintf(stderr, "ERROR: buildmode=c-archive should not run main\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
int r2 = check_handler();
|
||||
if (r2!=0) {
|
||||
return r2;
|
||||
}
|
||||
|
||||
res = FromPkg();
|
||||
if (res != 1024) {
|
||||
fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);
|
||||
return 2;
|
||||
}
|
||||
|
||||
CheckArgs();
|
||||
|
||||
fprintf(stderr, "PASS\n");
|
||||
return 0;
|
||||
}
|
||||
239
src/cmd/cgo/internal/testcarchive/testdata/main2.c
vendored
Normal file
239
src/cmd/cgo/internal/testcarchive/testdata/main2.c
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
// 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 installing a signal handler before the Go code starts.
|
||||
// This is a lot like ../testcshared/main4.c.
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libgo2.h"
|
||||
|
||||
static void die(const char* msg) {
|
||||
perror(msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t sigioSeen;
|
||||
static volatile sig_atomic_t sigpipeSeen;
|
||||
|
||||
// Use up some stack space.
|
||||
static void recur(int i, char *p) {
|
||||
char a[1024];
|
||||
|
||||
*p = '\0';
|
||||
if (i > 0) {
|
||||
recur(i - 1, a);
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
recur(4, a);
|
||||
sigioSeen = 1;
|
||||
}
|
||||
|
||||
static jmp_buf jmp;
|
||||
static char* nullPointer;
|
||||
|
||||
// An arbitrary function which requires proper stack alignment; see
|
||||
// http://golang.org/issue/17641.
|
||||
static void callWithVarargs(void* dummy, ...) {
|
||||
va_list args;
|
||||
va_start(args, dummy);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Signal handler for SIGSEGV on a C thread.
|
||||
static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
sigset_t mask;
|
||||
int i;
|
||||
|
||||
// Call an arbitrary function that requires the stack to be properly aligned.
|
||||
callWithVarargs("dummy arg", 3.1415);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Set up the signal handlers in a high priority constructor,
|
||||
// so that they are installed before the Go code starts.
|
||||
|
||||
static void init(void) __attribute__ ((constructor (200)));
|
||||
|
||||
static void init() {
|
||||
struct sigaction sa;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
sa.sa_sigaction = pipeHandler;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0) {
|
||||
die("sigaction");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int verbose;
|
||||
sigset_t mask;
|
||||
int i;
|
||||
struct timespec ts;
|
||||
int darwin;
|
||||
|
||||
darwin = atoi(argv[1]);
|
||||
|
||||
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 RunGoroutines\n");
|
||||
}
|
||||
|
||||
RunGoroutines();
|
||||
|
||||
// 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 SIGIO\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("provoking SIGPIPE\n");
|
||||
}
|
||||
|
||||
// SIGPIPE is never forwarded on Darwin, see golang.org/issue/33384.
|
||||
if (!darwin) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 TestSEGV\n");
|
||||
}
|
||||
|
||||
TestSEGV();
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
210
src/cmd/cgo/internal/testcarchive/testdata/main3.c
vendored
Normal file
210
src/cmd/cgo/internal/testcarchive/testdata/main3.c
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
// 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 os/signal.Notify and os/signal.Reset.
|
||||
// This is a lot like ../testcshared/main5.c.
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "libgo3.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;
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
static void *provokeSIGPIPE(void *arg) {
|
||||
ProvokeSIGPIPE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int verbose;
|
||||
struct sigaction sa;
|
||||
int i;
|
||||
struct timespec ts;
|
||||
int res;
|
||||
pthread_t tid;
|
||||
|
||||
verbose = argc > 2;
|
||||
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();
|
||||
|
||||
// Test that SIGPIPE on a non-main thread is also handled by Go.
|
||||
res = pthread_create(&tid, NULL, provokeSIGPIPE, NULL);
|
||||
if (res != 0) {
|
||||
fprintf(stderr, "pthread_create: %s\n", strerror(res));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
res = pthread_join(tid, NULL);
|
||||
if (res != 0) {
|
||||
fprintf(stderr, "pthread_join: %s\n", strerror(res));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
// 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 CatchSIGIO\n");
|
||||
}
|
||||
|
||||
CatchSIGIO();
|
||||
|
||||
if (verbose) {
|
||||
printf("raising SIGIO\n");
|
||||
}
|
||||
|
||||
if (raise(SIGIO) < 0) {
|
||||
die("raise");
|
||||
}
|
||||
|
||||
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 ResetSIGIO\n");
|
||||
}
|
||||
|
||||
ResetSIGIO();
|
||||
|
||||
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;
|
||||
}
|
||||
204
src/cmd/cgo/internal/testcarchive/testdata/main4.c
vendored
Normal file
204
src/cmd/cgo/internal/testcarchive/testdata/main4.c
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
// 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 a C thread that calls sigaltstack and then calls Go code.
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sched.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "libgo4.h"
|
||||
|
||||
#ifdef _AIX
|
||||
// On AIX, CSIGSTKSZ is too small to handle Go sighandler.
|
||||
#define CSIGSTKSZ 0x4000
|
||||
#else
|
||||
#define CSIGSTKSZ SIGSTKSZ
|
||||
#endif
|
||||
|
||||
static void die(const char* msg) {
|
||||
perror(msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int ok = 1;
|
||||
|
||||
static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
}
|
||||
|
||||
// Set up the SIGIO signal handler in a high priority constructor, so
|
||||
// that it is installed before the Go code starts.
|
||||
|
||||
static void init(void) __attribute__ ((constructor (200)));
|
||||
|
||||
static void init() {
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sa_sigaction = ioHandler;
|
||||
if (sigemptyset(&sa.sa_mask) < 0) {
|
||||
die("sigemptyset");
|
||||
}
|
||||
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
if (sigaction(SIGIO, &sa, NULL) < 0) {
|
||||
die("sigaction");
|
||||
}
|
||||
}
|
||||
|
||||
// Test raising SIGIO on a C thread with an alternate signal stack
|
||||
// when there is a Go signal handler for SIGIO.
|
||||
static void* thread1(void* arg __attribute__ ((unused))) {
|
||||
stack_t ss;
|
||||
int i;
|
||||
stack_t nss;
|
||||
struct timespec ts;
|
||||
|
||||
// Set up an alternate signal stack for this thread.
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ss.ss_sp = malloc(CSIGSTKSZ);
|
||||
if (ss.ss_sp == NULL) {
|
||||
die("malloc");
|
||||
}
|
||||
ss.ss_flags = 0;
|
||||
ss.ss_size = CSIGSTKSZ;
|
||||
if (sigaltstack(&ss, NULL) < 0) {
|
||||
die("sigaltstack");
|
||||
}
|
||||
|
||||
// Send ourselves a SIGIO. This will be caught by the Go
|
||||
// signal handler which should forward to the C signal
|
||||
// handler.
|
||||
i = pthread_kill(pthread_self(), SIGIO);
|
||||
if (i != 0) {
|
||||
fprintf(stderr, "pthread_kill: %s\n", strerror(i));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Wait until the signal has been delivered.
|
||||
i = 0;
|
||||
while (SIGIOCount() == 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// We should still be on the same signal stack.
|
||||
if (sigaltstack(NULL, &nss) < 0) {
|
||||
die("sigaltstack check");
|
||||
}
|
||||
if ((nss.ss_flags & SS_DISABLE) != 0) {
|
||||
fprintf(stderr, "sigaltstack disabled on return from Go\n");
|
||||
ok = 0;
|
||||
} else if (nss.ss_sp != ss.ss_sp) {
|
||||
fprintf(stderr, "sigaltstack changed on return from Go\n");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Test calling a Go function to raise SIGIO on a C thread with an
|
||||
// alternate signal stack when there is a Go signal handler for SIGIO.
|
||||
static void* thread2(void* arg __attribute__ ((unused))) {
|
||||
stack_t ss;
|
||||
int i;
|
||||
int oldcount;
|
||||
pthread_t tid;
|
||||
struct timespec ts;
|
||||
stack_t nss;
|
||||
|
||||
// Set up an alternate signal stack for this thread.
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ss.ss_sp = malloc(CSIGSTKSZ);
|
||||
if (ss.ss_sp == NULL) {
|
||||
die("malloc");
|
||||
}
|
||||
ss.ss_flags = 0;
|
||||
ss.ss_size = CSIGSTKSZ;
|
||||
if (sigaltstack(&ss, NULL) < 0) {
|
||||
die("sigaltstack");
|
||||
}
|
||||
|
||||
oldcount = SIGIOCount();
|
||||
|
||||
// Call a Go function that will call a C function to send us a
|
||||
// SIGIO.
|
||||
tid = pthread_self();
|
||||
GoRaiseSIGIO(&tid);
|
||||
|
||||
// Wait until the signal has been delivered.
|
||||
i = 0;
|
||||
while (SIGIOCount() == oldcount) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// We should still be on the same signal stack.
|
||||
if (sigaltstack(NULL, &nss) < 0) {
|
||||
die("sigaltstack check");
|
||||
}
|
||||
if ((nss.ss_flags & SS_DISABLE) != 0) {
|
||||
fprintf(stderr, "sigaltstack disabled on return from Go\n");
|
||||
ok = 0;
|
||||
} else if (nss.ss_sp != ss.ss_sp) {
|
||||
fprintf(stderr, "sigaltstack changed on return from Go\n");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
pthread_t tid;
|
||||
int i;
|
||||
|
||||
// Tell the Go library to start looking for SIGIO.
|
||||
GoCatchSIGIO();
|
||||
|
||||
i = pthread_create(&tid, NULL, thread1, NULL);
|
||||
if (i != 0) {
|
||||
fprintf(stderr, "pthread_create: %s\n", strerror(i));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
i = pthread_join(tid, NULL);
|
||||
if (i != 0) {
|
||||
fprintf(stderr, "pthread_join: %s\n", strerror(i));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
i = pthread_create(&tid, NULL, thread2, NULL);
|
||||
if (i != 0) {
|
||||
fprintf(stderr, "pthread_create: %s\n", strerror(i));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
i = pthread_join(tid, NULL);
|
||||
if (i != 0) {
|
||||
fprintf(stderr, "pthread_join: %s\n", strerror(i));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
105
src/cmd/cgo/internal/testcarchive/testdata/main5.c
vendored
Normal file
105
src/cmd/cgo/internal/testcarchive/testdata/main5.c
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// 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 for verifying that the Go runtime properly forwards
|
||||
// signals when non-Go signals are raised.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "libgo2.h"
|
||||
|
||||
int *nilp;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int verbose;
|
||||
int test;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Missing argument\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
test = atoi(argv[1]);
|
||||
|
||||
verbose = (argc > 2);
|
||||
|
||||
Noop();
|
||||
|
||||
switch (test) {
|
||||
case 1: {
|
||||
if (verbose) {
|
||||
printf("attempting segfault\n");
|
||||
}
|
||||
|
||||
*nilp = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
struct timeval tv;
|
||||
|
||||
if (verbose) {
|
||||
printf("attempting external signal test\n");
|
||||
}
|
||||
|
||||
fprintf(stderr, "OK\n");
|
||||
fflush(stderr);
|
||||
|
||||
// The program should be interrupted before
|
||||
// this sleep finishes. We use select rather
|
||||
// than sleep because in older versions of
|
||||
// glibc the sleep function does some signal
|
||||
// fiddling to handle SIGCHLD. If this
|
||||
// program is fiddling signals just when the
|
||||
// test program sends the signal, the signal
|
||||
// may be delivered to a Go thread which will
|
||||
// break this test.
|
||||
tv.tv_sec = 60;
|
||||
tv.tv_usec = 0;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
|
||||
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;
|
||||
}
|
||||
printf("did not receive SIGPIPE\n");
|
||||
return 0;
|
||||
}
|
||||
case 4: {
|
||||
fprintf(stderr, "OK\n");
|
||||
fflush(stderr);
|
||||
|
||||
if (verbose) {
|
||||
printf("calling Block\n");
|
||||
}
|
||||
Block();
|
||||
}
|
||||
default:
|
||||
printf("Unknown test: %d\n", test);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("FAIL\n");
|
||||
return 0;
|
||||
}
|
||||
34
src/cmd/cgo/internal/testcarchive/testdata/main6.c
vendored
Normal file
34
src/cmd/cgo/internal/testcarchive/testdata/main6.c
vendored
Normal file
@@ -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;
|
||||
}
|
||||
18
src/cmd/cgo/internal/testcarchive/testdata/main7.c
vendored
Normal file
18
src/cmd/cgo/internal/testcarchive/testdata/main7.c
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2019 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 lots of calls don't deadlock.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libgo7.h"
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100000; i++) {
|
||||
GoFunction7();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
16
src/cmd/cgo/internal/testcarchive/testdata/main8.c
vendored
Normal file
16
src/cmd/cgo/internal/testcarchive/testdata/main8.c
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2021 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 preemption.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libgo8.h"
|
||||
|
||||
int main() {
|
||||
GoFunction8();
|
||||
|
||||
// That should have exited the program.
|
||||
abort();
|
||||
}
|
||||
24
src/cmd/cgo/internal/testcarchive/testdata/main9.c
vendored
Normal file
24
src/cmd/cgo/internal/testcarchive/testdata/main9.c
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// 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.
|
||||
|
||||
#include "libgo9.h"
|
||||
|
||||
void use(int *x) { (*x)++; }
|
||||
|
||||
void callGoFWithDeepStack() {
|
||||
int x[10000];
|
||||
|
||||
use(&x[0]);
|
||||
use(&x[9999]);
|
||||
|
||||
GoF();
|
||||
|
||||
use(&x[0]);
|
||||
use(&x[9999]);
|
||||
}
|
||||
|
||||
int main() {
|
||||
GoF(); // call GoF without using much stack
|
||||
callGoFWithDeepStack(); // call GoF with a deep stack
|
||||
}
|
||||
59
src/cmd/cgo/internal/testcarchive/testdata/main_unix.c
vendored
Normal file
59
src/cmd/cgo/internal/testcarchive/testdata/main_unix.c
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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 <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct sigaction sa;
|
||||
struct sigaction osa;
|
||||
|
||||
static void (*oldHandler)(int, siginfo_t*, void*);
|
||||
|
||||
static void handler(int signo, siginfo_t* info, void* ctxt) {
|
||||
if (oldHandler) {
|
||||
oldHandler(signo, info, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
int install_handler() {
|
||||
// Install our own signal handler.
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sa_sigaction = handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||
memset(&osa, 0, sizeof osa);
|
||||
sigemptyset(&osa.sa_mask);
|
||||
if (sigaction(SIGSEGV, &sa, &osa) < 0) {
|
||||
perror("sigaction");
|
||||
return 2;
|
||||
}
|
||||
if (osa.sa_handler == SIG_DFL) {
|
||||
fprintf(stderr, "Go runtime did not install signal handler\n");
|
||||
return 2;
|
||||
}
|
||||
// gccgo does not set SA_ONSTACK for SIGSEGV.
|
||||
if (getenv("GCCGO") == NULL && (osa.sa_flags&SA_ONSTACK) == 0) {
|
||||
fprintf(stderr, "Go runtime did not install signal handler\n");
|
||||
return 2;
|
||||
}
|
||||
oldHandler = osa.sa_sigaction;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_handler() {
|
||||
if (sigaction(SIGSEGV, NULL, &sa) < 0) {
|
||||
perror("sigaction check");
|
||||
return 2;
|
||||
}
|
||||
if (sa.sa_sigaction != handler) {
|
||||
fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler);
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
17
src/cmd/cgo/internal/testcarchive/testdata/main_windows.c
vendored
Normal file
17
src/cmd/cgo/internal/testcarchive/testdata/main_windows.c
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* Dummy implementations for Windows, because Windows doesn't
|
||||
* support Unix-style signal handling.
|
||||
*/
|
||||
|
||||
int install_handler() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_handler() {
|
||||
return 0;
|
||||
}
|
||||
10
src/cmd/cgo/internal/testcarchive/testdata/p/p.go
vendored
Normal file
10
src/cmd/cgo/internal/testcarchive/testdata/p/p.go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// 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 }
|
||||
Reference in New Issue
Block a user