Fix race build error.

This adds a test to smoke-tests to ensure that the race build does not
break again. In debugging this issue, a race in the nogo tool itself
was discovered, and a related fix is included.

PiperOrigin-RevId: 424393624
This commit is contained in:
Adin Scannell
2022-01-26 11:08:21 -08:00
committed by gVisor bot
parent b57e94c303
commit c18ec0b53c
5 changed files with 33 additions and 29 deletions
+1
View File
@@ -187,6 +187,7 @@ debian: ## Builds the debian packages.
smoke-tests: ## Runs a simple smoke test after build runsc.
@$(call run,//runsc,--alsologtostderr --network none --debug --TESTONLY-unsafe-nonroot=true --rootless do true)
@$(call run,$(RACE_FLAGS) //runsc:runsc-race,--alsologtostderr --network none --debug --TESTONLY-unsafe-nonroot=true --rootless do true)
.PHONY: smoke-tests
nogo-tests:
+1
View File
@@ -40,6 +40,7 @@ BRANCH_NAME := $(shell (git branch --show-current 2>/dev/null || \
git rev-parse --abbrev-ref HEAD 2>/dev/null) | \
xargs -n 1 basename 2>/dev/null)
BUILD_ROOTS := bazel-bin/ bazel-out/
RACE_FLAGS := --@io_bazel_rules_go//go/config:race
# Bazel container configuration (see below).
USER := $(shell whoami)
+6
View File
@@ -34,6 +34,7 @@ def select_system(linux = ["__linux__"], darwin = [], **kwargs):
})
arch_config = [
"@io_bazel_rules_go//go/config:race",
"//command_line_option:cpu",
"//command_line_option:crosstool_top",
"//command_line_option:platforms",
@@ -41,6 +42,9 @@ arch_config = [
def arm64_config(settings, attr):
return {
# Race builds are always disabled for cross-architecture generation. We
# can't run it locally anyways, what value can this provide?
"@io_bazel_rules_go//go/config:race": False,
"//command_line_option:cpu": "aarch64",
"//command_line_option:crosstool_top": "@crosstool//:toolchains",
"//command_line_option:platforms": "@io_bazel_rules_go//go/toolchain:linux_arm64",
@@ -48,6 +52,8 @@ def arm64_config(settings, attr):
def amd64_config(settings, attr):
return {
# See above.
"@io_bazel_rules_go//go/config:race": False,
"//command_line_option:cpu": "k8",
"//command_line_option:crosstool_top": "@crosstool//:toolchains",
"//command_line_option:platforms": "@io_bazel_rules_go//go/toolchain:linux_amd64",
+6 -6
View File
@@ -112,7 +112,7 @@ nogo_stdlib = go_rule(
attrs = {
"_nogo": attr.label(
default = "//tools/nogo:nogo",
cfg = "host",
cfg = "exec",
),
"_target": attr.label(
default = "//tools/nogo:target",
@@ -319,7 +319,7 @@ nogo_aspect = go_rule(
attrs = {
"_nogo": attr.label(
default = "//tools/nogo:nogo",
cfg = "host",
cfg = "exec",
),
"_target": attr.label(
default = "//tools/nogo:target",
@@ -329,7 +329,7 @@ nogo_aspect = go_rule(
# appears to be reserved for some internal bazel use.
"_nogo_stdlib": attr.label(
default = "//tools/nogo:stdlib",
cfg = "host",
cfg = "target",
),
},
)
@@ -411,7 +411,7 @@ nogo_test = rule(
),
"_nogo": attr.label(
default = "//tools/nogo:nogo",
cfg = "host",
cfg = "exec",
),
"_target": attr.label(
default = "//tools/nogo:target",
@@ -493,12 +493,12 @@ nogo_facts = go_rule(
),
"_nogo": attr.label(
default = "//tools/nogo:nogo",
cfg = "host",
cfg = "exec",
),
# See _nogo_aspect, above.
"_nogo_stdlib": attr.label(
default = "//tools/nogo:stdlib",
cfg = "host",
cfg = "target",
),
"_target": attr.label(
default = "//tools/nogo:target",
+19 -23
View File
@@ -32,7 +32,6 @@ import (
"sort"
"strings"
"sync"
"time"
_ "net/http/pprof" // For profiling.
@@ -243,6 +242,19 @@ func allCacheStats() string {
return sb.String()
}
// safeBuffer is a trivial wrapper around bytes.Buffer.
type safeBuffer struct {
mu sync.Mutex
bytes.Buffer
}
// Write implements io.Writer.Write.
func (s *safeBuffer) Write(p []byte) (int, error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.Buffer.Write(p)
}
// Work invokes the main function.
func Work(run func([]string) int) {
flag.CommandLine.Parse(os.Args[1:])
@@ -298,8 +310,6 @@ func Work(run func([]string) int) {
log.Fatalf("unable to move stdout: %v", err)
}
}
// Best-effort: collect logs.
rPipe, wPipe, err := os.Pipe()
if err != nil {
log.Fatalf("unable to create pipe: %v", err)
@@ -310,8 +320,8 @@ func Work(run func([]string) int) {
if err := unix.Dup2(int(wPipe.Fd()), 2); err != nil {
log.Fatalf("error duping over stderr: %v", err)
}
wPipe.Close()
defer rPipe.Close()
wPipe.Close() // Still open at stdout, stderr.
rPipe.Close() // Read end of pipe is now closed.
// Read requests from stdin.
input := bufio.NewReader(os.NewFile(0, "input"))
@@ -348,30 +358,16 @@ func Work(run func([]string) int) {
}
// Prepare logging.
outputBuffer := bytes.NewBuffer(nil)
var outputBuffer safeBuffer
outputBuffer.WriteString(listenHeader)
log.SetOutput(outputBuffer)
log.SetOutput(&outputBuffer)
// Parse all arguments.
flag.CommandLine.Parse(wreq.GetArguments())
var exitCode int
exitChan := make(chan int)
go func() { exitChan <- run(flag.CommandLine.Args()) }()
for running := true; running; {
select {
case exitCode = <-exitChan:
running = false
default:
}
// N.B. rPipe is given a read deadline of 1ms. We expect
// this to turn a copy error after 1ms, and we just keep
// flushing this buffer while the task is running.
rPipe.SetReadDeadline(time.Now().Add(time.Millisecond))
outputBuffer.ReadFrom(rPipe)
}
exitCode := run(flag.CommandLine.Args())
// Attach all cache stats.
if *workerDebug {
// Attach all cache stats.
outputBuffer.WriteString(allCacheStats())
}