diff --git a/Makefile b/Makefile index ae33685f5..55b0bfe9c 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/tools/bazel.mk b/tools/bazel.mk index 4fc7662a4..5dce58cfb 100644 --- a/tools/bazel.mk +++ b/tools/bazel.mk @@ -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) diff --git a/tools/bazeldefs/defs.bzl b/tools/bazeldefs/defs.bzl index 71fd9776f..acf6bc659 100644 --- a/tools/bazeldefs/defs.bzl +++ b/tools/bazeldefs/defs.bzl @@ -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", diff --git a/tools/nogo/defs.bzl b/tools/nogo/defs.bzl index 67dfa8b4b..b1100fa50 100644 --- a/tools/nogo/defs.bzl +++ b/tools/nogo/defs.bzl @@ -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", diff --git a/tools/worker/worker.go b/tools/worker/worker.go index d0c1f2d56..3230bd9c8 100644 --- a/tools/worker/worker.go +++ b/tools/worker/worker.go @@ -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()) }