1. Dave Cheney
  2. go-debian-kfreebsd

Commits

Dave Cheney  committed cb38e94 Draft

net/http: fix race on bodyEOFSignal.isClosed

Update issue 4191.

Fixes unreported race failure at
http://build.golang.org/log/61e43a328fb220801d3d5c88cd91916cfc5dc43c

R=dvyukov, bradfitz
CC=golang-dev
http://codereview.appspot.com/6640057

  • Participants
  • Parent commits 18dffd0
  • Branches default

Comments (0)

Files changed (1)

File src/pkg/net/http/transport.go

View file
 	"os"
 	"strings"
 	"sync"
+	"sync/atomic"
 	"time"
 )
 
 type bodyEOFSignal struct {
 	body     io.ReadCloser
 	fn       func()
-	isClosed bool
+	isClosed uint32 // atomic bool, non-zero if true
 	once     sync.Once
 }
 
 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
 	n, err = es.body.Read(p)
-	if es.isClosed && n > 0 {
+	if es.closed() && n > 0 {
 		panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
 	}
 	if err == io.EOF {
 }
 
 func (es *bodyEOFSignal) Close() (err error) {
-	if es.isClosed {
+	if !es.setClosed() {
+		// already closed
 		return nil
 	}
-	es.isClosed = true
 	err = es.body.Close()
 	if err == nil {
 		es.condfn()
 	}
 }
 
+func (es *bodyEOFSignal) closed() bool {
+	return atomic.LoadUint32(&es.isClosed) != 0
+}
+
+func (es *bodyEOFSignal) setClosed() bool {
+	return atomic.CompareAndSwapUint32(&es.isClosed, 0, 1)
+}
+
 type readFirstCloseBoth struct {
 	io.ReadCloser
 	io.Closer