github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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 !plan9,!windows,!js 6 7 package runtime_test 8 9 import ( 10 "os/exec" 11 "syscall" 12 "testing" 13 "time" 14 ) 15 16 // Issue #27250. Spurious wakeups to pthread_cond_timedwait_relative_np 17 // shouldn't cause semasleep to retry with the same timeout which would 18 // cause indefinite spinning. 19 func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { 20 if *flagQuick { 21 t.Skip("-quick") 22 } 23 24 exe, err := buildTestProg(t, "testprog") 25 if err != nil { 26 t.Fatal(err) 27 } 28 29 start := time.Now() 30 cmd := exec.Command(exe, "After1") 31 if err := cmd.Start(); err != nil { 32 t.Fatalf("Failed to start command: %v", err) 33 } 34 doneCh := make(chan error, 1) 35 go func() { 36 doneCh <- cmd.Wait() 37 }() 38 39 // With the repro running, we can continuously send to it 40 // a non-terminal signal such as SIGIO, to spuriously 41 // wakeup pthread_cond_timedwait_relative_np. 42 unfixedTimer := time.NewTimer(2 * time.Second) 43 for { 44 select { 45 case <-time.After(200 * time.Millisecond): 46 // Send the pesky signal that toggles spinning 47 // indefinitely if #27520 is not fixed. 48 cmd.Process.Signal(syscall.SIGIO) 49 50 case <-unfixedTimer.C: 51 t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") 52 cmd.Process.Signal(syscall.SIGKILL) 53 return 54 55 case err := <-doneCh: 56 if err != nil { 57 t.Fatalf("The program returned but unfortunately with an error: %v", err) 58 } 59 if time.Since(start) < 100*time.Millisecond { 60 t.Fatalf("The program stopped too quickly.") 61 } 62 return 63 } 64 } 65 }