diff options
Diffstat (limited to 'src/runtime/semasleep_test.go')
-rw-r--r-- | src/runtime/semasleep_test.go | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go new file mode 100644 index 0000000..9b371b0 --- /dev/null +++ b/src/runtime/semasleep_test.go @@ -0,0 +1,65 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !plan9,!windows,!js + +package runtime_test + +import ( + "os/exec" + "syscall" + "testing" + "time" +) + +// Issue #27250. Spurious wakeups to pthread_cond_timedwait_relative_np +// shouldn't cause semasleep to retry with the same timeout which would +// cause indefinite spinning. +func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { + if *flagQuick { + t.Skip("-quick") + } + + exe, err := buildTestProg(t, "testprog") + if err != nil { + t.Fatal(err) + } + + start := time.Now() + cmd := exec.Command(exe, "After1") + if err := cmd.Start(); err != nil { + t.Fatalf("Failed to start command: %v", err) + } + doneCh := make(chan error, 1) + go func() { + doneCh <- cmd.Wait() + }() + + // With the repro running, we can continuously send to it + // a non-terminal signal such as SIGIO, to spuriously + // wakeup pthread_cond_timedwait_relative_np. + unfixedTimer := time.NewTimer(2 * time.Second) + for { + select { + case <-time.After(200 * time.Millisecond): + // Send the pesky signal that toggles spinning + // indefinitely if #27520 is not fixed. + cmd.Process.Signal(syscall.SIGIO) + + case <-unfixedTimer.C: + t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") + cmd.Process.Signal(syscall.SIGKILL) + return + + case err := <-doneCh: + if err != nil { + t.Fatalf("The program returned but unfortunately with an error: %v", err) + } + if time.Since(start) < 100*time.Millisecond { + t.Fatalf("The program stopped too quickly.") + } + return + } + } +} |