Closed
Description
What version of Go are you using (go version
)?
go version devel +4bb649fba8 Wed May 23 12:26:19 2018 +0000 linux/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
linux/amd64
What did you do?
While debugging #25619 it took me a while to realize that the scary runtime crash
$ go run timer.go
panic: (runtime.errorString) (0x46adc0,0x4d0dc0)
fatal error: panic holding locks
goroutine 20 [running]:
runtime.throw(0x47cb63, 0x13)
/home/elias/dev/go-tip/src/runtime/panic.go:589 +0x6a fp=0xc000045e20 sp=0xc000045df0 pc=0x422f2a
panic(0x46adc0, 0x4d0dc0)
/home/elias/dev/go-tip/src/runtime/panic.go:454 +0x3ab fp=0xc000045eb0 sp=0xc000045e20 pc=0x422c5b
runtime.panicindex()
/home/elias/dev/go-tip/src/runtime/panic.go:28 +0x5e fp=0xc000045ed0 sp=0xc000045eb0 pc=0x4219be
runtime.siftupTimer(0xc0000ac000, 0x3, 0x4, 0x5)
/home/elias/dev/go-tip/src/runtime/time.go:331 +0xe9 fp=0xc000045ee0 sp=0xc000045ed0 pc=0x43c929
runtime.(*timersBucket).addtimerLocked(0x4d63e0, 0xc000096008)
/home/elias/dev/go-tip/src/runtime/time.go:146 +0xa6 fp=0xc000045f30 sp=0xc000045ee0 pc=0x43c0e6
runtime.addtimer(0xc000096008)
/home/elias/dev/go-tip/src/runtime/time.go:131 +0x83 fp=0xc000045f60 sp=0xc000045f30 pc=0x43c013
time.startTimer(0xc000096008)
/home/elias/dev/go-tip/src/runtime/time.go:111 +0x2b fp=0xc000045f78 sp=0xc000045f60 pc=0x43bf2b
time.(*Timer).Reset(0xc000096000, 0x1476b081e8000, 0x1)
/home/elias/dev/go-tip/src/time/sleep.go:130 +0x81 fp=0xc000045fb0 sp=0xc000045f78 pc=0x455ed1
main.main.func1(0xc000096000)
/home/elias/snot/timer.go:10 +0x3a fp=0xc000045fd8 sp=0xc000045fb0 pc=0x45ab1a
runtime.goexit()
/home/elias/dev/go-tip/src/runtime/asm_amd64.s:1365 +0x1 fp=0xc000045fe0 sp=0xc000045fd8 pc=0x44a5b1
created by main.main
/home/elias/snot/timer.go:8 +0x60
could be caused by simple misuse of time.Timer.Reset. The above crash was easily reproduced with the (incorrect) program
package main
import "time"
func main() {
t := time.NewTimer(100 * time.Hour)
for i := 0; i < 8; i++ {
go func() {
for {
t.Reset(100 * time.Hour)
}
}()
}
select {}
}
What did you expect to see?
The detection of the concurrent use of time.Timer and a friendly crash, the same way concurrent accesses to map (sometimes) fail with a friendly error instead of corrupting memory.
What did you see instead?
A runtime crash "fatal error: panic holding locks", which lead me to believe that the Go runtime was at fault.