mirror of
https://github.com/golang/go
synced 2024-11-18 15:24:41 -07:00
time: prevent a panic from leaving the timer mutex held
When deleting a timer, a panic due to nil deref would leave a lock held, possibly leading to a deadlock in a defer. Instead return false on a nil timer. Fixes #5745. R=golang-dev, daniel.morsing, dvyukov, rsc, iant CC=golang-dev https://golang.org/cl/10373047
This commit is contained in:
parent
b86f6c9224
commit
0286b4738e
@ -131,6 +131,11 @@ runtime·deltimer(Timer *t)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
// Dereference t so that any panic happens before the lock is held.
|
||||
// Discard result, because t might be moving in the heap.
|
||||
i = t->i;
|
||||
USED(i);
|
||||
|
||||
runtime·lock(&timers);
|
||||
|
||||
// t may not be registered anymore and may have
|
||||
|
@ -314,3 +314,23 @@ func TestOverflowSleep(t *testing.T) {
|
||||
t.Fatalf("negative timeout didn't fire")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a panic while deleting a timer does not leave
|
||||
// the timers mutex held, deadlocking a ticker.Stop in a defer.
|
||||
func TestIssue5745(t *testing.T) {
|
||||
ticker := NewTicker(Hour)
|
||||
defer func() {
|
||||
// would deadlock here before the fix due to
|
||||
// lock taken before the segfault.
|
||||
ticker.Stop()
|
||||
|
||||
if r := recover(); r == nil {
|
||||
t.Error("Expected panic, but none happened.")
|
||||
}
|
||||
}()
|
||||
|
||||
// cause a panic due to a segfault
|
||||
var timer *Timer
|
||||
timer.Stop()
|
||||
t.Error("Should be unreachable.")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user