Initial commit: Go 1.23 release state

This commit is contained in:
Vorapol Rinsatitnon
2024-09-21 23:49:08 +10:00
commit 17cd57a668
13231 changed files with 3114330 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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)
}
}

View 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() {
}

View 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() {
}

View 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() {
}

View 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() {
}

View 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() {
}

View 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() {
}

View 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() }

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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();
}

View 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
}

View 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;
}

View 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;
}

View 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 }