]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: in TestSpuriousWakeupsNeverHangSemasleep, wait for the runtime to register...
authorBryan C. Mills <bcmills@google.com>
Mon, 22 Nov 2021 19:30:40 +0000 (14:30 -0500)
committerBryan C. Mills <bcmills@google.com>
Mon, 22 Nov 2021 20:34:30 +0000 (20:34 +0000)
According to https://man7.org/linux/man-pages/man7/signal.7.html, the
default behavior of SIGIO is to terminate the program. The Go runtime
changes that behavior with its own signal handler, so the program will
terminate if we send the signal before the runtime has finished
setting up.

Fixes #49727

Change-Id: I65db66f5176831c8d7454eebc0138d825c68e100
Reviewed-on: https://go-review.googlesource.com/c/go/+/366255
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/semasleep_test.go
src/runtime/testdata/testprog/sleep.go

index cf4ef1820849a425a6b066ce37888b98e123f17e..bc73140a2ad4ce07ca146d695e882d72e0a5c480 100644 (file)
@@ -7,6 +7,7 @@
 package runtime_test
 
 import (
+       "io"
        "os/exec"
        "syscall"
        "testing"
@@ -28,6 +29,10 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) {
 
        start := time.Now()
        cmd := exec.Command(exe, "After1")
+       stdout, err := cmd.StdoutPipe()
+       if err != nil {
+               t.Fatalf("StdoutPipe: %v", err)
+       }
        if err := cmd.Start(); err != nil {
                t.Fatalf("Failed to start command: %v", err)
        }
@@ -36,27 +41,43 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) {
                doneCh <- cmd.Wait()
        }()
 
+       // Wait for After1 to close its stdout so that we know the runtime's SIGIO
+       // handler is registered.
+       b, err := io.ReadAll(stdout)
+       if len(b) > 0 {
+               t.Logf("read from testprog stdout: %s", b)
+       }
+       if err != nil {
+               t.Fatalf("error reading from testprog: %v", err)
+       }
+
        // 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)
+       // a signal that the runtime considers non-terminal,
+       // such as SIGIO, to spuriously wake up
+       // pthread_cond_timedwait_relative_np.
+       ticker := time.NewTicker(200 * time.Millisecond)
+       defer ticker.Stop()
        for {
                select {
-               case <-time.After(200 * time.Millisecond):
+               case now := <-ticker.C:
+                       if now.Sub(start) > 2*time.Second {
+                               t.Error("Program failed to return on time and has to be killed, issue #27520 still exists")
+                               cmd.Process.Signal(syscall.SIGKILL)
+                               <-doneCh
+                               return
+                       }
+
                        // 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 {
+                       if time.Since(start) < 1*time.Second {
+                               // The program was supposed to sleep for a full (monotonic) second;
+                               // it should not return before that has elapsed.
                                t.Fatalf("The program stopped too quickly.")
                        }
                        return
index 86e2f6cfe6ce7f5387acda3161b91d5142e76e63..b230e60181793915cce9defbc687ef5663b0b674 100644 (file)
@@ -4,7 +4,10 @@
 
 package main
 
-import "time"
+import (
+       "os"
+       "time"
+)
 
 // for golang.org/issue/27250
 
@@ -13,5 +16,7 @@ func init() {
 }
 
 func After1() {
+       os.Stdout.WriteString("ready\n")
+       os.Stdout.Close()
        <-time.After(1 * time.Second)
 }