go: time: racy Timer access should either work or throw, not panic

2020-02-21T20:22:19-13d73b2/linux-arm

panic: runtime error: racy use of timers
	panic: err must be non-nil

goroutine 3372 [running]:
net/http.(*http2pipe).closeWithError(0xd6f774, 0xd6f7a8, 0x0, 0x0, 0x0)
	/workdir/go/src/net/http/h2_bundle.go:3558 +0x210
net/http.(*http2pipe).CloseWithError(...)
	/workdir/go/src/net/http/h2_bundle.go:3545
net/http.(*http2clientConnReadLoop).cleanup(0xc43fd4)
	/workdir/go/src/net/http/h2_bundle.go:8228 +0x21c
panic(0x467b60, 0x580c18)
	/workdir/go/src/runtime/panic.go:967 +0x118
time.stopTimer(0x10c9e84, 0x10a9ca8)
	/workdir/go/src/runtime/time.go:224 +0x1c
time.(*Timer).Stop(...)
	/workdir/go/src/time/sleep.go:78
net/http.http2bodyWriterState.on100(0xd6f760, 0x10c9e80, 0x10a9c80, 0xefc780, 0x10c9e40, 0x3b9aca00, 0x0)
	/workdir/go/src/net/http/h2_bundle.go:9057 +0x38
net/http.(*http2clientConnReadLoop).handleResponse(0xc43fd4, 0xd6f760, 0xefc800, 0xd6f760, 0x58a650, 0x2cdc78)
	/workdir/go/src/net/http/h2_bundle.go:8433 +0x2fc
net/http.(*http2clientConnReadLoop).processHeaders(0xc43fd4, 0xefc800, 0x0, 0x0)
	/workdir/go/src/net/http/h2_bundle.go:8355 +0x14c
net/http.(*http2clientConnReadLoop).run(0xc43fd4, 0x0, 0x0)
	/workdir/go/src/net/http/h2_bundle.go:8277 +0x648
net/http.(*http2ClientConn).readLoop(0xdb2000)
	/workdir/go/src/net/http/h2_bundle.go:8174 +0x60
created by net/http.(*http2Transport).newClientConn
	/workdir/go/src/net/http/h2_bundle.go:7174 +0x538
FAIL	net/http	6.612s

CC @ianlancetaylor @bradfitz @tombergan

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (15 by maintainers)

Commits related to this issue

Most upvoted comments

This panic was introduced in Go 1.11, so I guess it is not a Go 1.14 release blocker. Still think it should probably either be fixed or changed to a runtime.throw. The unexpected panic is problematic (see the nested panic in the trace above). Stop should either work or crash the program, not panic.

Just to be clear, the problem was not introduced in 1.11. The program above also fails with 1.10. What happened in 1.11 was that the problem changed from a throw saying “fatal error: panic holding locks” to a panic saying “runtime error: racy use of timers”. Changing from a throw to a panic was a mistake on my part. But changing from “panic holding locks” to “racy use of timers” was not.

Before 1.10 the problem still exists but is harder to reproduce. What changed in 1.10 was that we switched to many different timer buckets. With fewer timers in each bucket it’s easier to create a case in which siftupTimer gets an index out of range.

In any case we can do better with the new timers.