Commit fc807647 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime/race: tell race detector what memory Read/Write syscalls touch

Fixes #5567.

R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/10085043
parent 0f4897ae
...@@ -330,6 +330,22 @@ runtime·RaceWrite(void *addr) ...@@ -330,6 +330,22 @@ runtime·RaceWrite(void *addr)
memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true); memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true);
} }
// func RaceReadRange(addr unsafe.Pointer, len int)
#pragma textflag 7
void
runtime·RaceReadRange(void *addr, intgo len)
{
rangeaccess(addr, len, 1, 0, (uintptr)runtime·getcallerpc(&addr), false);
}
// func RaceWriteRange(addr unsafe.Pointer, len int)
#pragma textflag 7
void
runtime·RaceWriteRange(void *addr, intgo len)
{
rangeaccess(addr, len, 1, 0, (uintptr)runtime·getcallerpc(&addr), true);
}
// func RaceDisable() // func RaceDisable()
void void
runtime·RaceDisable(void) runtime·RaceDisable(void)
......
...@@ -24,6 +24,8 @@ func RaceReleaseMerge(addr unsafe.Pointer) ...@@ -24,6 +24,8 @@ func RaceReleaseMerge(addr unsafe.Pointer)
func RaceRead(addr unsafe.Pointer) func RaceRead(addr unsafe.Pointer)
func RaceWrite(addr unsafe.Pointer) func RaceWrite(addr unsafe.Pointer)
func RaceReadRange(addr unsafe.Pointer, len int)
func RaceWriteRange(addr unsafe.Pointer, len int)
func RaceSemacquire(s *uint32) func RaceSemacquire(s *uint32)
func RaceSemrelease(s *uint32) func RaceSemrelease(s *uint32)
...@@ -5,8 +5,11 @@ ...@@ -5,8 +5,11 @@
package race_test package race_test
import ( import (
"crypto/sha1"
"errors" "errors"
"fmt" "fmt"
"io"
"os"
"runtime" "runtime"
"sync" "sync"
"testing" "testing"
...@@ -1627,3 +1630,43 @@ func TestRaceNestedStruct(t *testing.T) { ...@@ -1627,3 +1630,43 @@ func TestRaceNestedStruct(t *testing.T) {
y.x.y = 42 y.x.y = 42
<-c <-c
} }
func TestRaceIssue5567(t *testing.T) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
in := make(chan []byte)
res := make(chan error)
go func() {
var err error
defer func() {
close(in)
res <- err
}()
path := "mop_test.go"
f, err := os.Open(path)
if err != nil {
return
}
defer f.Close()
var n, total int
b := make([]byte, 17) // the race is on b buffer
for err == nil {
n, err = f.Read(b)
total += n
if n > 0 {
in <- b[:n]
}
}
if err == io.EOF {
err = nil
}
}()
h := sha1.New()
for b := range in {
h.Write(b)
}
_ = h.Sum(nil)
err := <-res
if err != nil {
t.Fatal(err)
}
}
...@@ -20,3 +20,11 @@ func raceAcquire(addr unsafe.Pointer) { ...@@ -20,3 +20,11 @@ func raceAcquire(addr unsafe.Pointer) {
func raceReleaseMerge(addr unsafe.Pointer) { func raceReleaseMerge(addr unsafe.Pointer) {
runtime.RaceReleaseMerge(addr) runtime.RaceReleaseMerge(addr)
} }
func raceReadRange(addr unsafe.Pointer, len int) {
runtime.RaceReadRange(addr, len)
}
func raceWriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}
...@@ -17,3 +17,9 @@ func raceAcquire(addr unsafe.Pointer) { ...@@ -17,3 +17,9 @@ func raceAcquire(addr unsafe.Pointer) {
func raceReleaseMerge(addr unsafe.Pointer) { func raceReleaseMerge(addr unsafe.Pointer) {
} }
func raceReadRange(addr unsafe.Pointer, len int) {
}
func raceWriteRange(addr unsafe.Pointer, len int) {
}
...@@ -120,17 +120,10 @@ func Getppid() (ppid int) { ...@@ -120,17 +120,10 @@ func Getppid() (ppid int) {
} }
func Read(fd int, p []byte) (n int, err error) { func Read(fd int, p []byte) (n int, err error) {
n, err = Pread(fd, p, -1) return Pread(fd, p, -1)
if raceenabled && err == nil {
raceAcquire(unsafe.Pointer(&ioSync))
}
return
} }
func Write(fd int, p []byte) (n int, err error) { func Write(fd int, p []byte) (n int, err error) {
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))
}
return Pwrite(fd, p, -1) return Pwrite(fd, p, -1)
} }
......
...@@ -130,8 +130,13 @@ func (s Signal) String() string { ...@@ -130,8 +130,13 @@ func (s Signal) String() string {
func Read(fd int, p []byte) (n int, err error) { func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p) n, err = read(fd, p)
if raceenabled && err == nil { if raceenabled {
raceAcquire(unsafe.Pointer(&ioSync)) if n > 0 {
raceWriteRange(unsafe.Pointer(&p[0]), n)
}
if err == nil {
raceAcquire(unsafe.Pointer(&ioSync))
}
} }
return return
} }
...@@ -140,7 +145,11 @@ func Write(fd int, p []byte) (n int, err error) { ...@@ -140,7 +145,11 @@ func Write(fd int, p []byte) (n int, err error) {
if raceenabled { if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync)) raceReleaseMerge(unsafe.Pointer(&ioSync))
} }
return write(fd, p) n, err = write(fd, p)
if raceenabled && n > 0 {
raceReadRange(unsafe.Pointer(&p[0]), n)
}
return
} }
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
......
...@@ -272,6 +272,9 @@ func Read(fd Handle, p []byte) (n int, err error) { ...@@ -272,6 +272,9 @@ func Read(fd Handle, p []byte) (n int, err error) {
return 0, e return 0, e
} }
if raceenabled { if raceenabled {
if done > 0 {
raceWriteRange(unsafe.Pointer(&p[0]), int(done))
}
raceAcquire(unsafe.Pointer(&ioSync)) raceAcquire(unsafe.Pointer(&ioSync))
} }
return int(done), nil return int(done), nil
...@@ -286,6 +289,9 @@ func Write(fd Handle, p []byte) (n int, err error) { ...@@ -286,6 +289,9 @@ func Write(fd Handle, p []byte) (n int, err error) {
if e != nil { if e != nil {
return 0, e return 0, e
} }
if raceenabled && done > 0 {
raceReadRange(unsafe.Pointer(&p[0]), int(done))
}
return int(done), nil return int(done), nil
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment