1
0
mirror of https://github.com/golang/go synced 2024-09-30 11:28:36 -06:00

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>
This commit is contained in:
Bryan C. Mills 2020-05-19 01:29:11 -04:00
parent dfd613e0e4
commit f7f9c8f2fb

View File

@ -32,11 +32,11 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"os/exec"
"os/signal"
"sync"
"syscall"
"time"
@ -71,14 +71,15 @@ func EINTR() {
// 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 @@ func winch() {
// 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 @@ func testExec(wg *sync.WaitGroup) {
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 @@ func testExec(wg *sync.WaitGroup) {
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 @@ func testExec(wg *sync.WaitGroup) {
}()
}
// 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)
}