runtime: allocate fewer bytes during TestEINTR

This will hopefully address the occasional "runtime: out of memory"
failures observed on the openbsd-arm-jsing builder:
https://build.golang.org/log/c296d866e5d99ba401b18c1a2ff3e4d480e5238c

Also make the "spin" and "winch" loops concurrent instead of
sequential to cut down the test's running time.

Finally, change Block to coordinate by closing stdin instead of
sending SIGINT. The SIGINT handler wasn't necessarily registered by
the time the signal was sent.

Updates #20400
Updates #39043

Change-Id: Ie12fc75b87e33847dc25a12edb4126db27492da6
Reviewed-on: https://go-review.googlesource.com/c/go/+/234538
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/runtime/testdata/testprogcgo/eintr.go b/src/runtime/testdata/testprogcgo/eintr.go
index 58f0dd2..9d9435d 100644
--- a/src/runtime/testdata/testprogcgo/eintr.go
+++ b/src/runtime/testdata/testprogcgo/eintr.go
@@ -32,11 +32,11 @@
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"net"
 	"os"
 	"os/exec"
-	"os/signal"
 	"sync"
 	"syscall"
 	"time"
@@ -71,14 +71,15 @@
 // spin does CPU bound spinning and allocating for a millisecond,
 // to get a SIGURG.
 //go:noinline
-func spin() (float64, [][]byte) {
+func spin() (float64, []byte) {
 	stop := time.Now().Add(time.Millisecond)
 	r1 := 0.0
-	var r2 [][]byte
+	r2 := make([]byte, 200)
 	for time.Now().Before(stop) {
 		for i := 1; i < 1e6; i++ {
 			r1 += r1 / float64(i)
-			r2 = append(r2, bytes.Repeat([]byte{byte(i)}, 100))
+			r2 = append(r2, bytes.Repeat([]byte{byte(i)}, 100)...)
+			r2 = r2[100:]
 		}
 	}
 	return r1, r2
@@ -96,8 +97,13 @@
 
 // sendSomeSignals triggers a few SIGURG and SIGWINCH signals.
 func sendSomeSignals() {
-	spin()
+	done := make(chan struct{})
+	go func() {
+		spin()
+		close(done)
+	}()
 	winch()
+	<-done
 }
 
 // testPipe tests pipe operations.
@@ -212,6 +218,10 @@
 	go func() {
 		defer wg.Done()
 		cmd := exec.Command(os.Args[0], "Block")
+		stdin, err := cmd.StdinPipe()
+		if err != nil {
+			log.Fatal(err)
+		}
 		cmd.Stderr = new(bytes.Buffer)
 		cmd.Stdout = cmd.Stderr
 		if err := cmd.Start(); err != nil {
@@ -220,9 +230,7 @@
 
 		go func() {
 			sendSomeSignals()
-			if err := cmd.Process.Signal(os.Interrupt); err != nil {
-				panic(err)
-			}
+			stdin.Close()
 		}()
 
 		if err := cmd.Wait(); err != nil {
@@ -231,10 +239,7 @@
 	}()
 }
 
-// Block blocks until the process receives os.Interrupt.
+// Block blocks until stdin is closed.
 func Block() {
-	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt)
-	defer signal.Stop(c)
-	<-c
+	io.Copy(ioutil.Discard, os.Stdin)
 }