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