github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/semasleep_test.go (about) 1 // Copyright 2018 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 //+build !nacl,!plan9,!windows,!js 6 7 package runtime_test 8 9 import ( 10 "internal/testenv" 11 "io/ioutil" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "syscall" 16 "testing" 17 "time" 18 ) 19 20 // Issue #27250. Spurious wakeups to pthread_cond_timedwait_relative_np 21 // shouldn't cause semasleep to retry with the same timeout which would 22 // cause indefinite spinning. 23 func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { 24 testenv.MustHaveGoBuild(t) 25 tempDir, err := ioutil.TempDir("", "issue-27250") 26 if err != nil { 27 t.Fatalf("Failed to create the temp directory: %v", err) 28 } 29 defer os.RemoveAll(tempDir) 30 31 repro := ` 32 package main 33 34 import "time" 35 36 func main() { 37 <-time.After(1 * time.Second) 38 } 39 ` 40 mainPath := filepath.Join(tempDir, "main.go") 41 if err := ioutil.WriteFile(mainPath, []byte(repro), 0644); err != nil { 42 t.Fatalf("Failed to create temp file for repro.go: %v", err) 43 } 44 binaryPath := filepath.Join(tempDir, "binary") 45 46 // Build the binary so that we can send the signal to its PID. 47 out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", binaryPath, mainPath).CombinedOutput() 48 if err != nil { 49 t.Fatalf("Failed to compile the binary: err: %v\nOutput: %s\n", err, out) 50 } 51 if err := os.Chmod(binaryPath, 0755); err != nil { 52 t.Fatalf("Failed to chmod binary: %v", err) 53 } 54 55 // Now run the binary. 56 cmd := exec.Command(binaryPath) 57 if err := cmd.Start(); err != nil { 58 t.Fatalf("Failed to start command: %v", err) 59 } 60 doneCh := make(chan error, 1) 61 go func() { 62 doneCh <- cmd.Wait() 63 }() 64 65 // With the repro running, we can continuously send to it 66 // a non-terminal signal such as SIGIO, to spuriously 67 // wakeup pthread_cond_timedwait_relative_np. 68 unfixedTimer := time.NewTimer(2 * time.Second) 69 for { 70 select { 71 case <-time.After(200 * time.Millisecond): 72 // Send the pesky signal that toggles spinning 73 // indefinitely if #27520 is not fixed. 74 cmd.Process.Signal(syscall.SIGIO) 75 76 case <-unfixedTimer.C: 77 t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") 78 cmd.Process.Signal(syscall.SIGKILL) 79 return 80 81 case err := <-doneCh: 82 if err != nil { 83 t.Fatalf("The program returned but unfortunately with an error: %v", err) 84 } 85 return 86 } 87 } 88 }