Skip to content

net/http: race using same long/infinite Request.Body after first is cut off by server #12796

Closed
@rogpeppe

Description

@rogpeppe

This program:
http://play.golang.org/p/M1-UWKD33p
has the race condition below.

The reason is probably because the exit of the http.persistConn.writeLoop
goroutine is not waited for by the http request.

FWIW some of our current infrastructure relies heavily on being able
to make two successive requests using the same reader
(it seeks to the start before making the second request).

Reproduced with Go 1.4.3 and 1.5.1.

WARNING: DATA RACE
Read by goroutine 20:
  main.(*reader).Read()
      /home/alesstimec/Downloads/main.go:15 +0x44
  io/ioutil.(*nopCloser).Read()
      <autogenerated>:4 +0xa0
  io.ReadAtLeast()
      /usr/local/go/src/io/io.go:298 +0x118
  io.ReadFull()
      /usr/local/go/src/io/io.go:316 +0x76
  net/http.newTransferWriter()
      /usr/local/go/src/net/http/transfer.go:71 +0x11ce
  net/http.(*Request).write()
      /usr/local/go/src/net/http/request.go:435 +0xc8b
  net/http.(*persistConn).writeLoop()
      /usr/local/go/src/net/http/transport.go:1015 +0x316

Previous write by goroutine 11:
  main.(*reader).Read()
      /home/alesstimec/Downloads/main.go:15 +0x5a
  io/ioutil.(*nopCloser).Read()
      <autogenerated>:4 +0xa0
  io.(*multiReader).Read()
      /usr/local/go/src/io/multi.go:13 +0x10c
  io.copyBuffer()
      /usr/local/go/src/io/io.go:381 +0x281
  io.Copy()
      /usr/local/go/src/io/io.go:351 +0x78
  net/http.(*transferWriter).WriteBody()
      /usr/local/go/src/net/http/transfer.go:218 +0x39f
  net/http.(*Request).write()
      /usr/local/go/src/net/http/request.go:462 +0xed7
  net/http.(*persistConn).writeLoop()
      /usr/local/go/src/net/http/transport.go:1015 +0x316

Goroutine 20 (running) created at:
  net/http.(*Transport).dialConn()
      /usr/local/go/src/net/http/transport.go:686 +0x11e4
  net/http.(*Transport).getConn.func4()
      /usr/local/go/src/net/http/transport.go:549 +0x73

Goroutine 11 (finished) created at:
  net/http.(*Transport).dialConn()
      /usr/local/go/src/net/http/transport.go:686 +0x11e4
  net/http.(*Transport).getConn.func4()
      /usr/local/go/src/net/http/transport.go:549 +0x73
==================

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions