mirror of
https://github.com/octoleo/restic.git
synced 2024-11-28 07:46:36 +00:00
lock: fix timer expiry monitoring during standby
Monotonic timers are paused during standby. Thus these timers won't fire after waking up. Fall back to periodic polling to detect too large clock jumps. See https://github.com/golang/go/issues/35012 for a discussion of go timers during standby.
This commit is contained in:
parent
401e432e9d
commit
49126796d0
@ -119,7 +119,18 @@ func refreshLocks(ctx context.Context, lock *restic.Lock, lockInfo *lockContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func monitorLockRefresh(ctx context.Context, lock *restic.Lock, lockInfo *lockContext, refreshed <-chan struct{}) {
|
func monitorLockRefresh(ctx context.Context, lock *restic.Lock, lockInfo *lockContext, refreshed <-chan struct{}) {
|
||||||
timer := time.NewTimer(refreshabilityTimeout)
|
// time.Now() might use a monotonic timer which is paused during standby
|
||||||
|
// convert to unix time to ensure we compare real time values
|
||||||
|
lastRefresh := time.Now().Unix()
|
||||||
|
pollDuration := 1 * time.Second
|
||||||
|
if refreshInterval < pollDuration {
|
||||||
|
// require for TestLockFailedRefresh
|
||||||
|
pollDuration = refreshInterval / 5
|
||||||
|
}
|
||||||
|
// timers are paused during standby, which is a problem as the refresh timeout
|
||||||
|
// _must_ expire if the host was too long in standby. Thus fall back to periodic checks
|
||||||
|
// https://github.com/golang/go/issues/35012
|
||||||
|
timer := time.NewTimer(pollDuration)
|
||||||
defer func() {
|
defer func() {
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
lockInfo.cancel()
|
lockInfo.cancel()
|
||||||
@ -132,9 +143,14 @@ func monitorLockRefresh(ctx context.Context, lock *restic.Lock, lockInfo *lockCo
|
|||||||
debug.Log("terminate expiry monitoring")
|
debug.Log("terminate expiry monitoring")
|
||||||
return
|
return
|
||||||
case <-refreshed:
|
case <-refreshed:
|
||||||
// reset timer once the lock was refreshed successfully
|
lastRefresh = time.Now().Unix()
|
||||||
timer.Reset(refreshabilityTimeout)
|
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
|
if float64(time.Now().Unix()-lastRefresh) < refreshInterval.Seconds() {
|
||||||
|
// restart timer
|
||||||
|
timer.Reset(pollDuration)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
Warnf("Fatal: failed to refresh lock in time\n")
|
Warnf("Fatal: failed to refresh lock in time\n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user