67 lines
1.7 KiB
Go
67 lines
1.7 KiB
Go
// 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.
|
|
|
|
//go:build !plan9 && !windows && !js
|
|
// +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
|
|
}
|
|
}
|
|
}
|