github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/crash_cgo_test.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build cgo
     6  
     7  package runtime_test
     8  
     9  import (
    10  	"fmt"
    11  	"internal/goos"
    12  	"internal/testenv"
    13  	"os"
    14  	"os/exec"
    15  	"runtime"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  )
    21  
    22  func TestCgoCrashHandler(t *testing.T) {
    23  	t.Parallel()
    24  	testCrashHandler(t, true)
    25  }
    26  
    27  func TestCgoSignalDeadlock(t *testing.T) {
    28  	// Don't call t.Parallel, since too much work going on at the
    29  	// same time can cause the testprogcgo code to overrun its
    30  	// timeouts (issue #18598).
    31  
    32  	if testing.Short() && runtime.GOOS == "windows" {
    33  		t.Skip("Skipping in short mode") // takes up to 64 seconds
    34  	}
    35  	got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
    36  	want := "OK\n"
    37  	if got != want {
    38  		t.Fatalf("expected %q, but got:\n%s", want, got)
    39  	}
    40  }
    41  
    42  func TestCgoTraceback(t *testing.T) {
    43  	t.Parallel()
    44  	got := runTestProg(t, "testprogcgo", "CgoTraceback")
    45  	want := "OK\n"
    46  	if got != want {
    47  		t.Fatalf("expected %q, but got:\n%s", want, got)
    48  	}
    49  }
    50  
    51  func TestCgoCallbackGC(t *testing.T) {
    52  	t.Parallel()
    53  	switch runtime.GOOS {
    54  	case "plan9", "windows":
    55  		t.Skipf("no pthreads on %s", runtime.GOOS)
    56  	}
    57  	if testing.Short() {
    58  		switch {
    59  		case runtime.GOOS == "dragonfly":
    60  			t.Skip("see golang.org/issue/11990")
    61  		case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
    62  			t.Skip("too slow for arm builders")
    63  		case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
    64  			t.Skip("too slow for mips64x builders")
    65  		}
    66  	}
    67  	if testenv.Builder() == "darwin-amd64-10_14" {
    68  		// TODO(#23011): When the 10.14 builders are gone, remove this skip.
    69  		t.Skip("skipping due to platform bug on macOS 10.14; see https://golang.org/issue/43926")
    70  	}
    71  	got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
    72  	want := "OK\n"
    73  	if got != want {
    74  		t.Fatalf("expected %q, but got:\n%s", want, got)
    75  	}
    76  }
    77  
    78  func TestCgoExternalThreadPanic(t *testing.T) {
    79  	t.Parallel()
    80  	if runtime.GOOS == "plan9" {
    81  		t.Skipf("no pthreads on %s", runtime.GOOS)
    82  	}
    83  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
    84  	want := "panic: BOOM"
    85  	if !strings.Contains(got, want) {
    86  		t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
    87  	}
    88  }
    89  
    90  func TestCgoExternalThreadSIGPROF(t *testing.T) {
    91  	t.Parallel()
    92  	// issue 9456.
    93  	switch runtime.GOOS {
    94  	case "plan9", "windows":
    95  		t.Skipf("no pthreads on %s", runtime.GOOS)
    96  	}
    97  
    98  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
    99  	if want := "OK\n"; got != want {
   100  		t.Fatalf("expected %q, but got:\n%s", want, got)
   101  	}
   102  }
   103  
   104  func TestCgoExternalThreadSignal(t *testing.T) {
   105  	t.Parallel()
   106  	// issue 10139
   107  	switch runtime.GOOS {
   108  	case "plan9", "windows":
   109  		t.Skipf("no pthreads on %s", runtime.GOOS)
   110  	}
   111  
   112  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
   113  	if want := "OK\n"; got != want {
   114  		t.Fatalf("expected %q, but got:\n%s", want, got)
   115  	}
   116  }
   117  
   118  func TestCgoDLLImports(t *testing.T) {
   119  	// test issue 9356
   120  	if runtime.GOOS != "windows" {
   121  		t.Skip("skipping windows specific test")
   122  	}
   123  	got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
   124  	want := "OK\n"
   125  	if got != want {
   126  		t.Fatalf("expected %q, but got %v", want, got)
   127  	}
   128  }
   129  
   130  func TestCgoExecSignalMask(t *testing.T) {
   131  	t.Parallel()
   132  	// Test issue 13164.
   133  	switch runtime.GOOS {
   134  	case "windows", "plan9":
   135  		t.Skipf("skipping signal mask test on %s", runtime.GOOS)
   136  	}
   137  	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
   138  	want := "OK\n"
   139  	if got != want {
   140  		t.Errorf("expected %q, got %v", want, got)
   141  	}
   142  }
   143  
   144  func TestEnsureDropM(t *testing.T) {
   145  	t.Parallel()
   146  	// Test for issue 13881.
   147  	switch runtime.GOOS {
   148  	case "windows", "plan9":
   149  		t.Skipf("skipping dropm test on %s", runtime.GOOS)
   150  	}
   151  	got := runTestProg(t, "testprogcgo", "EnsureDropM")
   152  	want := "OK\n"
   153  	if got != want {
   154  		t.Errorf("expected %q, got %v", want, got)
   155  	}
   156  }
   157  
   158  // Test for issue 14387.
   159  // Test that the program that doesn't need any cgo pointer checking
   160  // takes about the same amount of time with it as without it.
   161  func TestCgoCheckBytes(t *testing.T) {
   162  	t.Parallel()
   163  	// Make sure we don't count the build time as part of the run time.
   164  	testenv.MustHaveGoBuild(t)
   165  	exe, err := buildTestProg(t, "testprogcgo")
   166  	if err != nil {
   167  		t.Fatal(err)
   168  	}
   169  
   170  	// Try it 10 times to avoid flakiness.
   171  	const tries = 10
   172  	var tot1, tot2 time.Duration
   173  	for i := 0; i < tries; i++ {
   174  		cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
   175  		cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
   176  
   177  		start := time.Now()
   178  		cmd.Run()
   179  		d1 := time.Since(start)
   180  
   181  		cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
   182  		cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
   183  
   184  		start = time.Now()
   185  		cmd.Run()
   186  		d2 := time.Since(start)
   187  
   188  		if d1*20 > d2 {
   189  			// The slow version (d2) was less than 20 times
   190  			// slower than the fast version (d1), so OK.
   191  			return
   192  		}
   193  
   194  		tot1 += d1
   195  		tot2 += d2
   196  	}
   197  
   198  	t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
   199  }
   200  
   201  func TestCgoPanicDeadlock(t *testing.T) {
   202  	t.Parallel()
   203  	// test issue 14432
   204  	got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
   205  	want := "panic: cgo error\n\n"
   206  	if !strings.HasPrefix(got, want) {
   207  		t.Fatalf("output does not start with %q:\n%s", want, got)
   208  	}
   209  }
   210  
   211  func TestCgoCCodeSIGPROF(t *testing.T) {
   212  	t.Parallel()
   213  	got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
   214  	want := "OK\n"
   215  	if got != want {
   216  		t.Errorf("expected %q got %v", want, got)
   217  	}
   218  }
   219  
   220  func TestCgoPprofCallback(t *testing.T) {
   221  	t.Parallel()
   222  	switch runtime.GOOS {
   223  	case "windows", "plan9":
   224  		t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
   225  	}
   226  	got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
   227  	want := "OK\n"
   228  	if got != want {
   229  		t.Errorf("expected %q got %v", want, got)
   230  	}
   231  }
   232  
   233  func TestCgoCrashTraceback(t *testing.T) {
   234  	t.Parallel()
   235  	switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
   236  	case "darwin/amd64":
   237  	case "linux/amd64":
   238  	case "linux/arm64":
   239  	case "linux/ppc64le":
   240  	default:
   241  		t.Skipf("not yet supported on %s", platform)
   242  	}
   243  	got := runTestProg(t, "testprogcgo", "CrashTraceback")
   244  	for i := 1; i <= 3; i++ {
   245  		if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
   246  			t.Errorf("missing cgo symbolizer:%d", i)
   247  		}
   248  	}
   249  }
   250  
   251  func TestCgoCrashTracebackGo(t *testing.T) {
   252  	t.Parallel()
   253  	switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
   254  	case "darwin/amd64":
   255  	case "linux/amd64":
   256  	case "linux/arm64":
   257  	case "linux/ppc64le":
   258  	default:
   259  		t.Skipf("not yet supported on %s", platform)
   260  	}
   261  	got := runTestProg(t, "testprogcgo", "CrashTracebackGo")
   262  	for i := 1; i <= 3; i++ {
   263  		want := fmt.Sprintf("main.h%d", i)
   264  		if !strings.Contains(got, want) {
   265  			t.Errorf("missing %s", want)
   266  		}
   267  	}
   268  }
   269  
   270  func TestCgoTracebackContext(t *testing.T) {
   271  	t.Parallel()
   272  	got := runTestProg(t, "testprogcgo", "TracebackContext")
   273  	want := "OK\n"
   274  	if got != want {
   275  		t.Errorf("expected %q got %v", want, got)
   276  	}
   277  }
   278  
   279  func TestCgoTracebackContextPreemption(t *testing.T) {
   280  	t.Parallel()
   281  	got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
   282  	want := "OK\n"
   283  	if got != want {
   284  		t.Errorf("expected %q got %v", want, got)
   285  	}
   286  }
   287  
   288  func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
   289  	t.Parallel()
   290  	if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64") {
   291  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   292  	}
   293  	testenv.MustHaveGoRun(t)
   294  
   295  	exe, err := buildTestProg(t, "testprogcgo", buildArg)
   296  	if err != nil {
   297  		t.Fatal(err)
   298  	}
   299  
   300  	cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
   301  	got, err := cmd.CombinedOutput()
   302  	if err != nil {
   303  		if testenv.Builder() == "linux-amd64-alpine" {
   304  			// See Issue 18243 and Issue 19938.
   305  			t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
   306  		}
   307  		t.Fatalf("%s\n\n%v", got, err)
   308  	}
   309  	fn := strings.TrimSpace(string(got))
   310  	defer os.Remove(fn)
   311  
   312  	for try := 0; try < 2; try++ {
   313  		cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces"))
   314  		// Check that pprof works both with and without explicit executable on command line.
   315  		if try == 0 {
   316  			cmd.Args = append(cmd.Args, exe, fn)
   317  		} else {
   318  			cmd.Args = append(cmd.Args, fn)
   319  		}
   320  
   321  		found := false
   322  		for i, e := range cmd.Env {
   323  			if strings.HasPrefix(e, "PPROF_TMPDIR=") {
   324  				cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
   325  				found = true
   326  				break
   327  			}
   328  		}
   329  		if !found {
   330  			cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
   331  		}
   332  
   333  		out, err := cmd.CombinedOutput()
   334  		t.Logf("%s:\n%s", cmd.Args, out)
   335  		if err != nil {
   336  			t.Error(err)
   337  			continue
   338  		}
   339  
   340  		trace := findTrace(string(out), top)
   341  		if len(trace) == 0 {
   342  			t.Errorf("%s traceback missing.", top)
   343  			continue
   344  		}
   345  		if trace[len(trace)-1] != bottom {
   346  			t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
   347  		}
   348  	}
   349  }
   350  
   351  func TestCgoPprof(t *testing.T) {
   352  	testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
   353  }
   354  
   355  func TestCgoPprofPIE(t *testing.T) {
   356  	testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
   357  }
   358  
   359  func TestCgoPprofThread(t *testing.T) {
   360  	testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
   361  }
   362  
   363  func TestCgoPprofThreadNoTraceback(t *testing.T) {
   364  	testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
   365  }
   366  
   367  func TestRaceProf(t *testing.T) {
   368  	if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
   369  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   370  	}
   371  
   372  	testenv.MustHaveGoRun(t)
   373  
   374  	// This test requires building various packages with -race, so
   375  	// it's somewhat slow.
   376  	if testing.Short() {
   377  		t.Skip("skipping test in -short mode")
   378  	}
   379  
   380  	exe, err := buildTestProg(t, "testprogcgo", "-race")
   381  	if err != nil {
   382  		t.Fatal(err)
   383  	}
   384  
   385  	got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
   386  	if err != nil {
   387  		t.Fatal(err)
   388  	}
   389  	want := "OK\n"
   390  	if string(got) != want {
   391  		t.Errorf("expected %q got %s", want, got)
   392  	}
   393  }
   394  
   395  func TestRaceSignal(t *testing.T) {
   396  	t.Parallel()
   397  	if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
   398  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   399  	}
   400  
   401  	testenv.MustHaveGoRun(t)
   402  
   403  	// This test requires building various packages with -race, so
   404  	// it's somewhat slow.
   405  	if testing.Short() {
   406  		t.Skip("skipping test in -short mode")
   407  	}
   408  
   409  	exe, err := buildTestProg(t, "testprogcgo", "-race")
   410  	if err != nil {
   411  		t.Fatal(err)
   412  	}
   413  
   414  	got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
   415  	if err != nil {
   416  		t.Logf("%s\n", got)
   417  		t.Fatal(err)
   418  	}
   419  	want := "OK\n"
   420  	if string(got) != want {
   421  		t.Errorf("expected %q got %s", want, got)
   422  	}
   423  }
   424  
   425  func TestCgoNumGoroutine(t *testing.T) {
   426  	switch runtime.GOOS {
   427  	case "windows", "plan9":
   428  		t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
   429  	}
   430  	t.Parallel()
   431  	got := runTestProg(t, "testprogcgo", "NumGoroutine")
   432  	want := "OK\n"
   433  	if got != want {
   434  		t.Errorf("expected %q got %v", want, got)
   435  	}
   436  }
   437  
   438  func TestCatchPanic(t *testing.T) {
   439  	t.Parallel()
   440  	switch runtime.GOOS {
   441  	case "plan9", "windows":
   442  		t.Skipf("no signals on %s", runtime.GOOS)
   443  	case "darwin":
   444  		if runtime.GOARCH == "amd64" {
   445  			t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
   446  		}
   447  	}
   448  
   449  	testenv.MustHaveGoRun(t)
   450  
   451  	exe, err := buildTestProg(t, "testprogcgo")
   452  	if err != nil {
   453  		t.Fatal(err)
   454  	}
   455  
   456  	for _, early := range []bool{true, false} {
   457  		cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
   458  		// Make sure a panic results in a crash.
   459  		cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
   460  		if early {
   461  			// Tell testprogcgo to install an early signal handler for SIGABRT
   462  			cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
   463  		}
   464  		if out, err := cmd.CombinedOutput(); err != nil {
   465  			t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
   466  		}
   467  	}
   468  }
   469  
   470  func TestCgoLockOSThreadExit(t *testing.T) {
   471  	switch runtime.GOOS {
   472  	case "plan9", "windows":
   473  		t.Skipf("no pthreads on %s", runtime.GOOS)
   474  	}
   475  	t.Parallel()
   476  	testLockOSThreadExit(t, "testprogcgo")
   477  }
   478  
   479  func TestWindowsStackMemoryCgo(t *testing.T) {
   480  	if runtime.GOOS != "windows" {
   481  		t.Skip("skipping windows specific test")
   482  	}
   483  	testenv.SkipFlaky(t, 22575)
   484  	o := runTestProg(t, "testprogcgo", "StackMemory")
   485  	stackUsage, err := strconv.Atoi(o)
   486  	if err != nil {
   487  		t.Fatalf("Failed to read stack usage: %v", err)
   488  	}
   489  	if expected, got := 100<<10, stackUsage; got > expected {
   490  		t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
   491  	}
   492  }
   493  
   494  func TestSigStackSwapping(t *testing.T) {
   495  	switch runtime.GOOS {
   496  	case "plan9", "windows":
   497  		t.Skipf("no sigaltstack on %s", runtime.GOOS)
   498  	}
   499  	t.Parallel()
   500  	got := runTestProg(t, "testprogcgo", "SigStack")
   501  	want := "OK\n"
   502  	if got != want {
   503  		t.Errorf("expected %q got %v", want, got)
   504  	}
   505  }
   506  
   507  func TestCgoTracebackSigpanic(t *testing.T) {
   508  	// Test unwinding over a sigpanic in C code without a C
   509  	// symbolizer. See issue #23576.
   510  	if runtime.GOOS == "windows" {
   511  		// On Windows if we get an exception in C code, we let
   512  		// the Windows exception handler unwind it, rather
   513  		// than injecting a sigpanic.
   514  		t.Skip("no sigpanic in C on windows")
   515  	}
   516  	t.Parallel()
   517  	got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
   518  	t.Log(got)
   519  	want := "runtime.sigpanic"
   520  	if !strings.Contains(got, want) {
   521  		t.Errorf("did not see %q in output", want)
   522  	}
   523  	// No runtime errors like "runtime: unexpected return pc".
   524  	nowant := "runtime: "
   525  	if strings.Contains(got, nowant) {
   526  		t.Errorf("unexpectedly saw %q in output", nowant)
   527  	}
   528  }
   529  
   530  func TestCgoPanicCallback(t *testing.T) {
   531  	t.Parallel()
   532  	got := runTestProg(t, "testprogcgo", "PanicCallback")
   533  	t.Log(got)
   534  	want := "panic: runtime error: invalid memory address or nil pointer dereference"
   535  	if !strings.Contains(got, want) {
   536  		t.Errorf("did not see %q in output", want)
   537  	}
   538  	want = "panic_callback"
   539  	if !strings.Contains(got, want) {
   540  		t.Errorf("did not see %q in output", want)
   541  	}
   542  	want = "PanicCallback"
   543  	if !strings.Contains(got, want) {
   544  		t.Errorf("did not see %q in output", want)
   545  	}
   546  	// No runtime errors like "runtime: unexpected return pc".
   547  	nowant := "runtime: "
   548  	if strings.Contains(got, nowant) {
   549  		t.Errorf("did not see %q in output", want)
   550  	}
   551  }
   552  
   553  // Test that C code called via cgo can use large Windows thread stacks
   554  // and call back in to Go without crashing. See issue #20975.
   555  //
   556  // See also TestBigStackCallbackSyscall.
   557  func TestBigStackCallbackCgo(t *testing.T) {
   558  	if runtime.GOOS != "windows" {
   559  		t.Skip("skipping windows specific test")
   560  	}
   561  	t.Parallel()
   562  	got := runTestProg(t, "testprogcgo", "BigStack")
   563  	want := "OK\n"
   564  	if got != want {
   565  		t.Errorf("expected %q got %v", want, got)
   566  	}
   567  }
   568  
   569  func nextTrace(lines []string) ([]string, []string) {
   570  	var trace []string
   571  	for n, line := range lines {
   572  		if strings.HasPrefix(line, "---") {
   573  			return trace, lines[n+1:]
   574  		}
   575  		fields := strings.Fields(strings.TrimSpace(line))
   576  		if len(fields) == 0 {
   577  			continue
   578  		}
   579  		// Last field contains the function name.
   580  		trace = append(trace, fields[len(fields)-1])
   581  	}
   582  	return nil, nil
   583  }
   584  
   585  func findTrace(text, top string) []string {
   586  	lines := strings.Split(text, "\n")
   587  	_, lines = nextTrace(lines) // Skip the header.
   588  	for len(lines) > 0 {
   589  		var t []string
   590  		t, lines = nextTrace(lines)
   591  		if len(t) == 0 {
   592  			continue
   593  		}
   594  		if t[0] == top {
   595  			return t
   596  		}
   597  	}
   598  	return nil
   599  }
   600  
   601  func TestSegv(t *testing.T) {
   602  	switch runtime.GOOS {
   603  	case "plan9", "windows":
   604  		t.Skipf("no signals on %s", runtime.GOOS)
   605  	}
   606  
   607  	for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} {
   608  		test := test
   609  
   610  		// The tgkill variants only run on Linux.
   611  		if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") {
   612  			continue
   613  		}
   614  
   615  		t.Run(test, func(t *testing.T) {
   616  			t.Parallel()
   617  			got := runTestProg(t, "testprogcgo", test)
   618  			t.Log(got)
   619  			want := "SIGSEGV"
   620  			if !strings.Contains(got, want) {
   621  				if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
   622  					testenv.SkipFlaky(t, 39457)
   623  				}
   624  				t.Errorf("did not see %q in output", want)
   625  			}
   626  
   627  			// No runtime errors like "runtime: unknown pc".
   628  			switch runtime.GOOS {
   629  			case "darwin", "illumos", "solaris":
   630  				// Runtime sometimes throws when generating the traceback.
   631  				testenv.SkipFlaky(t, 49182)
   632  			case "linux":
   633  				if runtime.GOARCH == "386" {
   634  					// Runtime throws when generating a traceback from
   635  					// a VDSO call via asmcgocall.
   636  					testenv.SkipFlaky(t, 50504)
   637  				}
   638  			}
   639  			if test == "SegvInCgo" && strings.Contains(got, "unknown pc") {
   640  				testenv.SkipFlaky(t, 50979)
   641  			}
   642  
   643  			for _, nowant := range []string{"fatal error: ", "runtime: "} {
   644  				if strings.Contains(got, nowant) {
   645  					if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") {
   646  						// See the comment in signal_darwin_amd64.go.
   647  						t.Skip("skipping due to Darwin handling of malformed addresses")
   648  					}
   649  					t.Errorf("unexpectedly saw %q in output", nowant)
   650  				}
   651  			}
   652  		})
   653  	}
   654  }
   655  
   656  func TestAbortInCgo(t *testing.T) {
   657  	switch runtime.GOOS {
   658  	case "plan9", "windows":
   659  		// N.B. On Windows, C abort() causes the program to exit
   660  		// without going through the runtime at all.
   661  		t.Skipf("no signals on %s", runtime.GOOS)
   662  	}
   663  
   664  	t.Parallel()
   665  	got := runTestProg(t, "testprogcgo", "Abort")
   666  	t.Log(got)
   667  	want := "SIGABRT"
   668  	if !strings.Contains(got, want) {
   669  		t.Errorf("did not see %q in output", want)
   670  	}
   671  	// No runtime errors like "runtime: unknown pc".
   672  	nowant := "runtime: "
   673  	if strings.Contains(got, nowant) {
   674  		t.Errorf("did not see %q in output", want)
   675  	}
   676  }
   677  
   678  // TestEINTR tests that we handle EINTR correctly.
   679  // See issue #20400 and friends.
   680  func TestEINTR(t *testing.T) {
   681  	switch runtime.GOOS {
   682  	case "plan9", "windows":
   683  		t.Skipf("no EINTR on %s", runtime.GOOS)
   684  	case "linux":
   685  		if runtime.GOARCH == "386" {
   686  			// On linux-386 the Go signal handler sets
   687  			// a restorer function that is not preserved
   688  			// by the C sigaction call in the test,
   689  			// causing the signal handler to crash when
   690  			// returning the normal code. The test is not
   691  			// architecture-specific, so just skip on 386
   692  			// rather than doing a complicated workaround.
   693  			t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
   694  		}
   695  	}
   696  
   697  	t.Parallel()
   698  	output := runTestProg(t, "testprogcgo", "EINTR")
   699  	want := "OK\n"
   700  	if output != want {
   701  		t.Fatalf("want %s, got %s\n", want, output)
   702  	}
   703  }
   704  
   705  // Issue #42207.
   706  func TestNeedmDeadlock(t *testing.T) {
   707  	switch runtime.GOOS {
   708  	case "plan9", "windows":
   709  		t.Skipf("no signals on %s", runtime.GOOS)
   710  	}
   711  	output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
   712  	want := "OK\n"
   713  	if output != want {
   714  		t.Fatalf("want %s, got %s\n", want, output)
   715  	}
   716  }
   717  
   718  func TestCgoTracebackGoroutineProfile(t *testing.T) {
   719  	output := runTestProg(t, "testprogcgo", "GoroutineProfile")
   720  	want := "OK\n"
   721  	if output != want {
   722  		t.Fatalf("want %s, got %s\n", want, output)
   723  	}
   724  }
   725  
   726  func TestCgoTraceParser(t *testing.T) {
   727  	// Test issue 29707.
   728  	switch runtime.GOOS {
   729  	case "plan9", "windows":
   730  		t.Skipf("no pthreads on %s", runtime.GOOS)
   731  	}
   732  	output := runTestProg(t, "testprogcgo", "CgoTraceParser")
   733  	want := "OK\n"
   734  	ErrTimeOrder := "ErrTimeOrder\n"
   735  	if output == ErrTimeOrder {
   736  		t.Skipf("skipping due to golang.org/issue/16755: %v", output)
   737  	} else if output != want {
   738  		t.Fatalf("want %s, got %s\n", want, output)
   739  	}
   740  }
   741  
   742  func TestCgoTraceParserWithOneProc(t *testing.T) {
   743  	// Test issue 29707.
   744  	switch runtime.GOOS {
   745  	case "plan9", "windows":
   746  		t.Skipf("no pthreads on %s", runtime.GOOS)
   747  	}
   748  	output := runTestProg(t, "testprogcgo", "CgoTraceParser", "GOMAXPROCS=1")
   749  	want := "OK\n"
   750  	ErrTimeOrder := "ErrTimeOrder\n"
   751  	if output == ErrTimeOrder {
   752  		t.Skipf("skipping due to golang.org/issue/16755: %v", output)
   753  	} else if output != want {
   754  		t.Fatalf("GOMAXPROCS=1, want %s, got %s\n", want, output)
   755  	}
   756  }
   757  
   758  func TestCgoSigfwd(t *testing.T) {
   759  	t.Parallel()
   760  	if !goos.IsUnix {
   761  		t.Skipf("no signals on %s", runtime.GOOS)
   762  	}
   763  
   764  	got := runTestProg(t, "testprogcgo", "CgoSigfwd", "GO_TEST_CGOSIGFWD=1")
   765  	if want := "OK\n"; got != want {
   766  		t.Fatalf("expected %q, but got:\n%s", want, got)
   767  	}
   768  }