|
|
Descriptionmime/multipart: delay reading random source
If a user sets his/her own boundary string with SetBoundary,
we don't need to call randomBoundary at all.
Patch Set 1 #Patch Set 2 : diff -r 9eacb9c0d810 https://code.google.com/p/go #Patch Set 3 : diff -r 6146799f32ed https://code.google.com/p/go #Patch Set 4 : diff -r c860a8702b1b https://code.google.com/p/go #
MessagesTotal messages: 6
Hello golang-codereviews@googlegroups.com, I'd like you to review this change to https://code.google.com/p/go
Sign in to reply to this message.
LGTM
Sign in to reply to this message.
*** Submitted as https://code.google.com/p/go/source/detail?r=b2131d729e52 *** mime/multipart: delay reading random source If a user sets his/her own boundary string with SetBoundary, we don't need to call randomBoundary at all. LGTM=bradfitz R=golang-codereviews, bradfitz CC=golang-codereviews https://codereview.appspot.com/95760043
Sign in to reply to this message.
This broke Camlistore. We didn't believe it at first and thought our continuous build (which tests both Go release & Go tip) was broken, but two of us have now independently confirmed that tests pass immediately before this change and reliably fail with this change. The server reports errors like: 2014/08/05 11:05:58 Client error: Error reading multipart section: multipart: NextPart: EOF I haven't identified exactly why yet, though. The change still looks safe to my eyes. On Tue, Jul 29, 2014 at 6:24 PM, <ruiu@google.com> wrote: > *** Submitted as > https://code.google.com/p/go/source/detail?r=b2131d729e52 *** > > mime/multipart: delay reading random source > > If a user sets his/her own boundary string with SetBoundary, > we don't need to call randomBoundary at all. > > LGTM=bradfitz > R=golang-codereviews, bradfitz > CC=golang-codereviews > https://codereview.appspot.com/95760043 > > > https://codereview.appspot.com/95760043/ >
Sign in to reply to this message.
I see. It's a data race. Camlistore does: pipeReader, pipeWriter := io.Pipe() multipartWriter := *multipart.NewWriter*(pipeWriter) copyResult := make(chan error, 1) go func() { defer pipeWriter.Close() part, err := *multipartWriter.CreateFormFile*(blobrefStr, blobrefStr) if err != nil { copyResult <- err return } _, err = io.Copy(part, bodyReader) if err == nil { err = multipartWriter.Close() } copyResult <- err }() uploadURL := fmt.Sprintf("%s/camli/upload", pfx) req := c.newRequest("POST", uploadURL) req.Header.Set("Content-Type", *multipartWriter.FormDataContentType* ()) ================== WARNING: DATA RACE Read by goroutine 32: mime/multipart.(*Writer).Boundary() /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:34 +0x4c mime/multipart.(*Writer).CreatePart() /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:96 +0x975 mime/multipart.(*Writer).CreateFormFile() /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:131 +0x27e camlistore.org/pkg/client.func·013() <http://camlistore.org/pkg/client.func%C2%B7013()> /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:436 +0xe6 Previous write by goroutine 31: mime/multipart.(*Writer).Boundary() /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:35 +0x86 mime/multipart.(*Writer).FormDataContentType() /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:70 +0x46 camlistore.org/pkg/client.(*Client).Upload() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:453 +0x1ac5 camlistore.org/pkg/client.(*Client).ReceiveBlob() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/get.go:177 +0x2bc main.(*noStatReceiver).ReceiveBlob() <autogenerated>:166 +0xd1 camlistore.org/pkg/blobserver.receive() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:50 +0x2b8 camlistore.org/pkg/blobserver.ReceiveNoHash() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:42 +0xaf camlistore.org/pkg/schema.uploadString() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:197 +0x30e camlistore.org/pkg/schema.func·008() <http://camlistore.org/pkg/schema.func%C2%B7008()> /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:367 +0xf5 Goroutine 32 (running) created at: camlistore.org/pkg/client.(*Client).Upload() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:446 +0x1958 camlistore.org/pkg/client.(*Client).ReceiveBlob() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/get.go:177 +0x2bc main.(*noStatReceiver).ReceiveBlob() <autogenerated>:166 +0xd1 camlistore.org/pkg/blobserver.receive() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:50 +0x2b8 camlistore.org/pkg/blobserver.ReceiveNoHash() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:42 +0xaf camlistore.org/pkg/schema.uploadString() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:197 +0x30e camlistore.org/pkg/schema.func·008() <http://camlistore.org/pkg/schema.func%C2%B7008()> /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:367 +0xf5 Goroutine 31 (running) created at: camlistore.org/pkg/schema.func·009() <http://camlistore.org/pkg/schema.func%C2%B7009()> /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:373 +0x437 camlistore.org/pkg/schema.writeFileChunks() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:382 +0x6ca camlistore.org/pkg/schema.writeFileMapRolling() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:312 +0xa1 camlistore.org/pkg/schema.WriteFileMap() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:78 +0x90 main.(*Uploader).uploadNodeRegularFile() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:631 +0x13ad main.(*Uploader).uploadNode() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:381 +0xc7 main.func·018() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:1040 +0x1a9 main.(*nodeWorker).work() /Users/bradfitz/src/ camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/chanworker.go:116 +0x115 ================== On Tue, Aug 5, 2014 at 11:12 AM, Brad Fitzpatrick <bradfitz@golang.org> wrote: > This broke Camlistore. > > We didn't believe it at first and thought our continuous build (which > tests both Go release & Go tip) was broken, but two of us have now > independently confirmed that tests pass immediately before this change and > reliably fail with this change. > > The server reports errors like: > 2014/08/05 11:05:58 Client error: Error reading multipart section: > multipart: NextPart: EOF > > I haven't identified exactly why yet, though. The change still looks safe > to my eyes. > > > > > On Tue, Jul 29, 2014 at 6:24 PM, <ruiu@google.com> wrote: > >> *** Submitted as >> https://code.google.com/p/go/source/detail?r=b2131d729e52 *** >> >> mime/multipart: delay reading random source >> >> If a user sets his/her own boundary string with SetBoundary, >> we don't need to call randomBoundary at all. >> >> LGTM=bradfitz >> R=golang-codereviews, bradfitz >> CC=golang-codereviews >> https://codereview.appspot.com/95760043 >> >> >> https://codereview.appspot.com/95760043/ >> > >
Sign in to reply to this message.
Message was sent while issue was closed.
On 2014/08/05 18:24:04, bradfitz wrote: > I see. It's a data race. > > Camlistore does: > > pipeReader, pipeWriter := io.Pipe() > multipartWriter := *multipart.NewWriter*(pipeWriter) > > copyResult := make(chan error, 1) > go func() { > defer pipeWriter.Close() > part, err := *multipartWriter.CreateFormFile*(blobrefStr, > blobrefStr) > if err != nil { > copyResult <- err > return > } > _, err = io.Copy(part, bodyReader) > if err == nil { > err = multipartWriter.Close() > } > copyResult <- err > }() > > uploadURL := fmt.Sprintf("%s/camli/upload", pfx) > req := c.newRequest("POST", uploadURL) > req.Header.Set("Content-Type", *multipartWriter.FormDataContentType* > ()) > > ================== > WARNING: DATA RACE > Read by goroutine 32: > mime/multipart.(*Writer).Boundary() > /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:34 +0x4c > mime/multipart.(*Writer).CreatePart() > /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:96 +0x975 > mime/multipart.(*Writer).CreateFormFile() > /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:131 +0x27e > camlistore.org/pkg/client.func·013() > <http://camlistore.org/pkg/client.func%C2%B7013()> > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:436 > +0xe6 > > Previous write by goroutine 31: > mime/multipart.(*Writer).Boundary() > /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:35 +0x86 > mime/multipart.(*Writer).FormDataContentType() > /Users/bradfitz/go/src/pkg/mime/multipart/writer.go:70 +0x46 > camlistore.org/pkg/client.(*Client).Upload() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:453 > +0x1ac5 > camlistore.org/pkg/client.(*Client).ReceiveBlob() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/get.go:177 > +0x2bc > main.(*noStatReceiver).ReceiveBlob() > <autogenerated>:166 +0xd1 > camlistore.org/pkg/blobserver.receive() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:50 > +0x2b8 > camlistore.org/pkg/blobserver.ReceiveNoHash() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:42 > +0xaf > camlistore.org/pkg/schema.uploadString() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:197 > +0x30e > camlistore.org/pkg/schema.func·008() > <http://camlistore.org/pkg/schema.func%C2%B7008()> > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:367 > +0xf5 > > Goroutine 32 (running) created at: > camlistore.org/pkg/client.(*Client).Upload() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/upload.go:446 > +0x1958 > camlistore.org/pkg/client.(*Client).ReceiveBlob() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/client/get.go:177 > +0x2bc > main.(*noStatReceiver).ReceiveBlob() > <autogenerated>:166 +0xd1 > camlistore.org/pkg/blobserver.receive() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:50 > +0x2b8 > camlistore.org/pkg/blobserver.ReceiveNoHash() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/blobserver/receive.go:42 > +0xaf > camlistore.org/pkg/schema.uploadString() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:197 > +0x30e > camlistore.org/pkg/schema.func·008() > <http://camlistore.org/pkg/schema.func%C2%B7008()> > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:367 > +0xf5 > > Goroutine 31 (running) created at: > camlistore.org/pkg/schema.func·009() > <http://camlistore.org/pkg/schema.func%C2%B7009()> > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:373 > +0x437 > camlistore.org/pkg/schema.writeFileChunks() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:382 > +0x6ca > camlistore.org/pkg/schema.writeFileMapRolling() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:312 > +0xa1 > camlistore.org/pkg/schema.WriteFileMap() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/pkg/schema/filewriter.go:78 > +0x90 > main.(*Uploader).uploadNodeRegularFile() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:631 > +0x13ad > main.(*Uploader).uploadNode() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:381 > +0xc7 > main.func·018() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/files.go:1040 > +0x1a9 > main.(*nodeWorker).work() > /Users/bradfitz/src/ > camlistore.org/tmp/build-gopath-nosqlite/src/camlistore.org/cmd/camput/chanworker.go:116 > +0x115 > ================== > > > On Tue, Aug 5, 2014 at 11:12 AM, Brad Fitzpatrick <mailto:bradfitz@golang.org> > wrote: > > > This broke Camlistore. > > > > We didn't believe it at first and thought our continuous build (which > > tests both Go release & Go tip) was broken, but two of us have now > > independently confirmed that tests pass immediately before this change and > > reliably fail with this change. > > > > The server reports errors like: > > 2014/08/05 11:05:58 Client error: Error reading multipart section: > > multipart: NextPart: EOF > > > > I haven't identified exactly why yet, though. The change still looks safe > > to my eyes. > > > > > > > > > > On Tue, Jul 29, 2014 at 6:24 PM, <mailto:ruiu@google.com> wrote: > > > >> *** Submitted as > >> https://code.google.com/p/go/source/detail?r=b2131d729e52 *** > >> > >> mime/multipart: delay reading random source > >> > >> If a user sets his/her own boundary string with SetBoundary, > >> we don't need to call randomBoundary at all. > >> > >> LGTM=bradfitz > >> R=golang-codereviews, bradfitz > >> CC=golang-codereviews > >> https://codereview.appspot.com/95760043 > >> > >> > >> https://codereview.appspot.com/95760043/ > >> > > > > Can we have this as a test in std lib? We have so few good concurrent tests...
Sign in to reply to this message.
|