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;
|
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);
|
runtime·lock(&timers);
|
||||||
|
|
||||||
// t may not be registered anymore and may have
|
// 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")
|
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