From: Rob Pike
-Data races are one of the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. See the The Go Memory Model for details.
+Data races are among the most common and hardest to debug types of bugs in concurrent systems.
+A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.
+See the The Go Memory Model for details.
@@ -32,7 +34,8 @@ func main() {
-Fortunately, Go includes a built-in data race detector. To use it, add the
-When the race detector finds a data race in the program, it prints a report. The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created. For example:
+When the race detector finds a data race in the program, it prints a report.
+The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created.
+Here is an example:
-The
-When you build with
To start, run your tests using the race detector (
The variable
-The fix is to introduce new variables in the goroutines (note
-If the following code is called from several goroutines, it leads to bad races on the
-Data races can happen on variables of primitive types as well (
-Even such “innocent” data races can lead to hard to debug problems caused by (1) non-atomicity of the memory accesses, (2) interference with compiler optimizations and (3) processor memory access reordering issues.
+Even such "innocent" data races can lead to hard-to-debug problems caused by
+non-atomicity of the memory accesses,
+interference with compiler optimizations,
+or reordering issues accessing processor memory .
A typical fix for this race is to use a channel or a mutex.
-To preserve the lock-free behavior, one can also use the Introduction
Usage
-race
flag to the go command:
+To help diangose such bugs, Go includes a built-in data race detector.
+To use it, add the -race
flag to the go command:
@@ -45,7 +48,9 @@ $ go install -race mypkg // to install the package
Report Format
@@ -86,7 +91,8 @@ Goroutine 184 (running) created at:
Options
GORACE
environment variable sets race detector options. The format is:
+The GORACE
environment variable sets race detector options.
+The format is:
@@ -100,7 +106,8 @@ The options are:
@@ -134,9 +141,10 @@ $ GORACE="log_path=/tmp/race/report strip_path_prefix=/my/go/sources/" go test -
log_path
(default stderr
): The race detector writes
-its report to a file named log_path.pid. The special names stdout
+its report to a file named log_path.pid
.
+The special names stdout
and stderr
cause reports to be written to standard output and
standard error, respectively.
history_size
(default 1
): The per-goroutine memory
-access history is 32K * 2**history_size elements
. Increasing this
-value can avoid a "failed to restore the stack" error in reports, but at the
+access history is 32K * 2**history_size elements
.
+Increasing this value can avoid a "failed to restore the stack" error in reports, at the
cost of increased memory usage.
Excluding Tests
-race
flag, go command defines additional
+When you build with -race
flag, the go
command defines additional
build tag race
.
-You can use it to exclude some code/tests under the race detector. For example:
+You can use the tag to exclude some code and tests when running the race detector.
+Some examples:
@@ -165,7 +173,8 @@ func TestBaz(t *testing.T) {
go test -race
).
The race detector only finds races that happen at runtime, so it can't find
-races in code paths that are not executed. If your tests have incomplete coverage,
+races in code paths that are not executed.
+If your tests have incomplete coverage,
you may find more races by running a binary built with -race
under a realistic
workload.
i
in the function literal is the same variable used by the loop, so
-the read in the goroutine races with the loop increment. (This program typically
-prints 55555, not 01234.) The program can be fixed by making a copy of the
-variable:
+the read in the goroutine races with the loop increment.
+(This program typically prints 55555, not 01234.)
+The program can be fixed by making a copy of the variable:
@@ -246,7 +255,7 @@ func ParallelWrite(data []byte) chan error {
:=
):
+The fix is to introduce new variables in the goroutines (note the use of :=
):
@@ -260,8 +269,8 @@ The fix is to introduce new variables in the goroutines (note
:=
):
Unprotected global variable
service
map.
-Concurrent reads and writes of a map are not safe:
+If the following code is called from several goroutines, it leads to races on the service
map.
+Concurrent reads and writes of the same map are not safe:
@@ -302,7 +311,8 @@ func LookupService(name string) net.Addr {
Primitive unprotected variable
bool
, int
, int64
, etc.), like in the following example:
+Data races can happen on variables of primitive types as well (bool
, int
, int64
, etc.),
+as in this example:
@@ -327,12 +337,16 @@ func (w *Watchdog) Start() {
sync/atomic
package.
+To preserve the lock-free behavior, one can also use the
+sync/atomic
package.
diff --git a/doc/go1.1.html b/doc/go1.1.html
index 22e3f15f63..80f5ae1e48 100644
--- a/doc/go1.1.html
+++ b/doc/go1.1.html
@@ -285,6 +285,17 @@ Programs that depend on the old behavior should be modified to avoid the issue.
The byte-order-mark change is strictly backward-compatible.
+A major addition to the tools is a race detector, a way to find
+bugs in programs caused by problems like concurrent changes to the same variable.
+This new facility is built into the go
tool.
+To enable it, set the the -race
flag when building or testing your program
+(for instance, go test -race
).
+The race detector is documented in a separate article.
+
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go index 6cab37b486..00e03e9bda 100644 --- a/src/cmd/go/env.go +++ b/src/cmd/go/env.go @@ -42,6 +42,7 @@ func mkEnv() []envVar { {"GOHOSTOS", runtime.GOOS}, {"GOOS", goos}, {"GOPATH", os.Getenv("GOPATH")}, + {"GORACE", os.Getenv("GORACE")}, {"GOROOT", goroot}, {"GOTOOLDIR", toolDir}, }