Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/crash_cgo_test.go

Documentation: runtime

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

View as plain text