wait.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package wait
  14. import (
  15. "context"
  16. "errors"
  17. "math"
  18. "math/rand"
  19. "sync"
  20. "time"
  21. "k8s.io/apimachinery/pkg/util/clock"
  22. "k8s.io/apimachinery/pkg/util/runtime"
  23. )
  24. // For any test of the style:
  25. // ...
  26. // <- time.After(timeout):
  27. // t.Errorf("Timed out")
  28. // The value for timeout should effectively be "forever." Obviously we don't want our tests to truly lock up forever, but 30s
  29. // is long enough that it is effectively forever for the things that can slow down a run on a heavily contended machine
  30. // (GC, seeks, etc), but not so long as to make a developer ctrl-c a test run if they do happen to break that test.
  31. var ForeverTestTimeout = time.Second * 30
  32. // NeverStop may be passed to Until to make it never stop.
  33. var NeverStop <-chan struct{} = make(chan struct{})
  34. // Group allows to start a group of goroutines and wait for their completion.
  35. type Group struct {
  36. wg sync.WaitGroup
  37. }
  38. func (g *Group) Wait() {
  39. g.wg.Wait()
  40. }
  41. // StartWithChannel starts f in a new goroutine in the group.
  42. // stopCh is passed to f as an argument. f should stop when stopCh is available.
  43. func (g *Group) StartWithChannel(stopCh <-chan struct{}, f func(stopCh <-chan struct{})) {
  44. g.Start(func() {
  45. f(stopCh)
  46. })
  47. }
  48. // StartWithContext starts f in a new goroutine in the group.
  49. // ctx is passed to f as an argument. f should stop when ctx.Done() is available.
  50. func (g *Group) StartWithContext(ctx context.Context, f func(context.Context)) {
  51. g.Start(func() {
  52. f(ctx)
  53. })
  54. }
  55. // Start starts f in a new goroutine in the group.
  56. func (g *Group) Start(f func()) {
  57. g.wg.Add(1)
  58. go func() {
  59. defer g.wg.Done()
  60. f()
  61. }()
  62. }
  63. // Forever calls f every period for ever.
  64. //
  65. // Forever is syntactic sugar on top of Until.
  66. func Forever(f func(), period time.Duration) {
  67. Until(f, period, NeverStop)
  68. }
  69. // Until loops until stop channel is closed, running f every period.
  70. //
  71. // Until is syntactic sugar on top of JitterUntil with zero jitter factor and
  72. // with sliding = true (which means the timer for period starts after the f
  73. // completes).
  74. func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
  75. JitterUntil(f, period, 0.0, true, stopCh)
  76. }
  77. // UntilWithContext loops until context is done, running f every period.
  78. //
  79. // UntilWithContext is syntactic sugar on top of JitterUntilWithContext
  80. // with zero jitter factor and with sliding = true (which means the timer
  81. // for period starts after the f completes).
  82. func UntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
  83. JitterUntilWithContext(ctx, f, period, 0.0, true)
  84. }
  85. // NonSlidingUntil loops until stop channel is closed, running f every
  86. // period.
  87. //
  88. // NonSlidingUntil is syntactic sugar on top of JitterUntil with zero jitter
  89. // factor, with sliding = false (meaning the timer for period starts at the same
  90. // time as the function starts).
  91. func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
  92. JitterUntil(f, period, 0.0, false, stopCh)
  93. }
  94. // NonSlidingUntilWithContext loops until context is done, running f every
  95. // period.
  96. //
  97. // NonSlidingUntilWithContext is syntactic sugar on top of JitterUntilWithContext
  98. // with zero jitter factor, with sliding = false (meaning the timer for period
  99. // starts at the same time as the function starts).
  100. func NonSlidingUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
  101. JitterUntilWithContext(ctx, f, period, 0.0, false)
  102. }
  103. // JitterUntil loops until stop channel is closed, running f every period.
  104. //
  105. // If jitterFactor is positive, the period is jittered before every run of f.
  106. // If jitterFactor is not positive, the period is unchanged and not jittered.
  107. //
  108. // If sliding is true, the period is computed after f runs. If it is false then
  109. // period includes the runtime for f.
  110. //
  111. // Close stopCh to stop. f may not be invoked if stop channel is already
  112. // closed. Pass NeverStop to if you don't want it stop.
  113. func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
  114. BackoffUntil(f, NewJitteredBackoffManager(period, jitterFactor, &clock.RealClock{}), sliding, stopCh)
  115. }
  116. // BackoffUntil loops until stop channel is closed, run f every duration given by BackoffManager.
  117. //
  118. // If sliding is true, the period is computed after f runs. If it is false then
  119. // period includes the runtime for f.
  120. func BackoffUntil(f func(), backoff BackoffManager, sliding bool, stopCh <-chan struct{}) {
  121. var t clock.Timer
  122. for {
  123. select {
  124. case <-stopCh:
  125. return
  126. default:
  127. }
  128. if !sliding {
  129. t = backoff.Backoff()
  130. }
  131. func() {
  132. defer runtime.HandleCrash()
  133. f()
  134. }()
  135. if sliding {
  136. t = backoff.Backoff()
  137. }
  138. // NOTE: b/c there is no priority selection in golang
  139. // it is possible for this to race, meaning we could
  140. // trigger t.C and stopCh, and t.C select falls through.
  141. // In order to mitigate we re-check stopCh at the beginning
  142. // of every loop to prevent extra executions of f().
  143. select {
  144. case <-stopCh:
  145. return
  146. case <-t.C():
  147. }
  148. }
  149. }
  150. // JitterUntilWithContext loops until context is done, running f every period.
  151. //
  152. // If jitterFactor is positive, the period is jittered before every run of f.
  153. // If jitterFactor is not positive, the period is unchanged and not jittered.
  154. //
  155. // If sliding is true, the period is computed after f runs. If it is false then
  156. // period includes the runtime for f.
  157. //
  158. // Cancel context to stop. f may not be invoked if context is already expired.
  159. func JitterUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration, jitterFactor float64, sliding bool) {
  160. JitterUntil(func() { f(ctx) }, period, jitterFactor, sliding, ctx.Done())
  161. }
  162. // Jitter returns a time.Duration between duration and duration + maxFactor *
  163. // duration.
  164. //
  165. // This allows clients to avoid converging on periodic behavior. If maxFactor
  166. // is 0.0, a suggested default value will be chosen.
  167. func Jitter(duration time.Duration, maxFactor float64) time.Duration {
  168. if maxFactor <= 0.0 {
  169. maxFactor = 1.0
  170. }
  171. wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
  172. return wait
  173. }
  174. // ErrWaitTimeout is returned when the condition exited without success.
  175. var ErrWaitTimeout = errors.New("timed out waiting for the condition")
  176. // ConditionFunc returns true if the condition is satisfied, or an error
  177. // if the loop should be aborted.
  178. type ConditionFunc func() (done bool, err error)
  179. // runConditionWithCrashProtection runs a ConditionFunc with crash protection
  180. func runConditionWithCrashProtection(condition ConditionFunc) (bool, error) {
  181. defer runtime.HandleCrash()
  182. return condition()
  183. }
  184. // Backoff holds parameters applied to a Backoff function.
  185. type Backoff struct {
  186. // The initial duration.
  187. Duration time.Duration
  188. // Duration is multiplied by factor each iteration, if factor is not zero
  189. // and the limits imposed by Steps and Cap have not been reached.
  190. // Should not be negative.
  191. // The jitter does not contribute to the updates to the duration parameter.
  192. Factor float64
  193. // The sleep at each iteration is the duration plus an additional
  194. // amount chosen uniformly at random from the interval between
  195. // zero and `jitter*duration`.
  196. Jitter float64
  197. // The remaining number of iterations in which the duration
  198. // parameter may change (but progress can be stopped earlier by
  199. // hitting the cap). If not positive, the duration is not
  200. // changed. Used for exponential backoff in combination with
  201. // Factor and Cap.
  202. Steps int
  203. // A limit on revised values of the duration parameter. If a
  204. // multiplication by the factor parameter would make the duration
  205. // exceed the cap then the duration is set to the cap and the
  206. // steps parameter is set to zero.
  207. Cap time.Duration
  208. }
  209. // Step (1) returns an amount of time to sleep determined by the
  210. // original Duration and Jitter and (2) mutates the provided Backoff
  211. // to update its Steps and Duration.
  212. func (b *Backoff) Step() time.Duration {
  213. if b.Steps < 1 {
  214. if b.Jitter > 0 {
  215. return Jitter(b.Duration, b.Jitter)
  216. }
  217. return b.Duration
  218. }
  219. b.Steps--
  220. duration := b.Duration
  221. // calculate the next step
  222. if b.Factor != 0 {
  223. b.Duration = time.Duration(float64(b.Duration) * b.Factor)
  224. if b.Cap > 0 && b.Duration > b.Cap {
  225. b.Duration = b.Cap
  226. b.Steps = 0
  227. }
  228. }
  229. if b.Jitter > 0 {
  230. duration = Jitter(duration, b.Jitter)
  231. }
  232. return duration
  233. }
  234. // contextForChannel derives a child context from a parent channel.
  235. //
  236. // The derived context's Done channel is closed when the returned cancel function
  237. // is called or when the parent channel is closed, whichever happens first.
  238. //
  239. // Note the caller must *always* call the CancelFunc, otherwise resources may be leaked.
  240. func contextForChannel(parentCh <-chan struct{}) (context.Context, context.CancelFunc) {
  241. ctx, cancel := context.WithCancel(context.Background())
  242. go func() {
  243. select {
  244. case <-parentCh:
  245. cancel()
  246. case <-ctx.Done():
  247. }
  248. }()
  249. return ctx, cancel
  250. }
  251. // BackoffManager manages backoff with a particular scheme based on its underlying implementation. It provides
  252. // an interface to return a timer for backoff, and caller shall backoff until Timer.C() drains. If the second Backoff()
  253. // is called before the timer from the first Backoff() call finishes, the first timer will NOT be drained and result in
  254. // undetermined behavior.
  255. // The BackoffManager is supposed to be called in a single-threaded environment.
  256. type BackoffManager interface {
  257. Backoff() clock.Timer
  258. }
  259. type exponentialBackoffManagerImpl struct {
  260. backoff *Backoff
  261. backoffTimer clock.Timer
  262. lastBackoffStart time.Time
  263. initialBackoff time.Duration
  264. backoffResetDuration time.Duration
  265. clock clock.Clock
  266. }
  267. // NewExponentialBackoffManager returns a manager for managing exponential backoff. Each backoff is jittered and
  268. // backoff will not exceed the given max. If the backoff is not called within resetDuration, the backoff is reset.
  269. // This backoff manager is used to reduce load during upstream unhealthiness.
  270. func NewExponentialBackoffManager(initBackoff, maxBackoff, resetDuration time.Duration, backoffFactor, jitter float64, c clock.Clock) BackoffManager {
  271. return &exponentialBackoffManagerImpl{
  272. backoff: &Backoff{
  273. Duration: initBackoff,
  274. Factor: backoffFactor,
  275. Jitter: jitter,
  276. // the current impl of wait.Backoff returns Backoff.Duration once steps are used up, which is not
  277. // what we ideally need here, we set it to max int and assume we will never use up the steps
  278. Steps: math.MaxInt32,
  279. Cap: maxBackoff,
  280. },
  281. backoffTimer: nil,
  282. initialBackoff: initBackoff,
  283. lastBackoffStart: c.Now(),
  284. backoffResetDuration: resetDuration,
  285. clock: c,
  286. }
  287. }
  288. func (b *exponentialBackoffManagerImpl) getNextBackoff() time.Duration {
  289. if b.clock.Now().Sub(b.lastBackoffStart) > b.backoffResetDuration {
  290. b.backoff.Steps = math.MaxInt32
  291. b.backoff.Duration = b.initialBackoff
  292. }
  293. b.lastBackoffStart = b.clock.Now()
  294. return b.backoff.Step()
  295. }
  296. // Backoff implements BackoffManager.Backoff, it returns a timer so caller can block on the timer for exponential backoff.
  297. // The returned timer must be drained before calling Backoff() the second time
  298. func (b *exponentialBackoffManagerImpl) Backoff() clock.Timer {
  299. if b.backoffTimer == nil {
  300. b.backoffTimer = b.clock.NewTimer(b.getNextBackoff())
  301. } else {
  302. b.backoffTimer.Reset(b.getNextBackoff())
  303. }
  304. return b.backoffTimer
  305. }
  306. type jitteredBackoffManagerImpl struct {
  307. clock clock.Clock
  308. duration time.Duration
  309. jitter float64
  310. backoffTimer clock.Timer
  311. }
  312. // NewJitteredBackoffManager returns a BackoffManager that backoffs with given duration plus given jitter. If the jitter
  313. // is negative, backoff will not be jittered.
  314. func NewJitteredBackoffManager(duration time.Duration, jitter float64, c clock.Clock) BackoffManager {
  315. return &jitteredBackoffManagerImpl{
  316. clock: c,
  317. duration: duration,
  318. jitter: jitter,
  319. backoffTimer: nil,
  320. }
  321. }
  322. func (j *jitteredBackoffManagerImpl) getNextBackoff() time.Duration {
  323. jitteredPeriod := j.duration
  324. if j.jitter > 0.0 {
  325. jitteredPeriod = Jitter(j.duration, j.jitter)
  326. }
  327. return jitteredPeriod
  328. }
  329. // Backoff implements BackoffManager.Backoff, it returns a timer so caller can block on the timer for jittered backoff.
  330. // The returned timer must be drained before calling Backoff() the second time
  331. func (j *jitteredBackoffManagerImpl) Backoff() clock.Timer {
  332. backoff := j.getNextBackoff()
  333. if j.backoffTimer == nil {
  334. j.backoffTimer = j.clock.NewTimer(backoff)
  335. } else {
  336. j.backoffTimer.Reset(backoff)
  337. }
  338. return j.backoffTimer
  339. }
  340. // ExponentialBackoff repeats a condition check with exponential backoff.
  341. //
  342. // It repeatedly checks the condition and then sleeps, using `backoff.Step()`
  343. // to determine the length of the sleep and adjust Duration and Steps.
  344. // Stops and returns as soon as:
  345. // 1. the condition check returns true or an error,
  346. // 2. `backoff.Steps` checks of the condition have been done, or
  347. // 3. a sleep truncated by the cap on duration has been completed.
  348. // In case (1) the returned error is what the condition function returned.
  349. // In all other cases, ErrWaitTimeout is returned.
  350. func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error {
  351. for backoff.Steps > 0 {
  352. if ok, err := runConditionWithCrashProtection(condition); err != nil || ok {
  353. return err
  354. }
  355. if backoff.Steps == 1 {
  356. break
  357. }
  358. time.Sleep(backoff.Step())
  359. }
  360. return ErrWaitTimeout
  361. }
  362. // Poll tries a condition func until it returns true, an error, or the timeout
  363. // is reached.
  364. //
  365. // Poll always waits the interval before the run of 'condition'.
  366. // 'condition' will always be invoked at least once.
  367. //
  368. // Some intervals may be missed if the condition takes too long or the time
  369. // window is too short.
  370. //
  371. // If you want to Poll something forever, see PollInfinite.
  372. func Poll(interval, timeout time.Duration, condition ConditionFunc) error {
  373. return pollInternal(poller(interval, timeout), condition)
  374. }
  375. func pollInternal(wait WaitFunc, condition ConditionFunc) error {
  376. done := make(chan struct{})
  377. defer close(done)
  378. return WaitFor(wait, condition, done)
  379. }
  380. // PollImmediate tries a condition func until it returns true, an error, or the timeout
  381. // is reached.
  382. //
  383. // PollImmediate always checks 'condition' before waiting for the interval. 'condition'
  384. // will always be invoked at least once.
  385. //
  386. // Some intervals may be missed if the condition takes too long or the time
  387. // window is too short.
  388. //
  389. // If you want to immediately Poll something forever, see PollImmediateInfinite.
  390. func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error {
  391. return pollImmediateInternal(poller(interval, timeout), condition)
  392. }
  393. func pollImmediateInternal(wait WaitFunc, condition ConditionFunc) error {
  394. done, err := runConditionWithCrashProtection(condition)
  395. if err != nil {
  396. return err
  397. }
  398. if done {
  399. return nil
  400. }
  401. return pollInternal(wait, condition)
  402. }
  403. // PollInfinite tries a condition func until it returns true or an error
  404. //
  405. // PollInfinite always waits the interval before the run of 'condition'.
  406. //
  407. // Some intervals may be missed if the condition takes too long or the time
  408. // window is too short.
  409. func PollInfinite(interval time.Duration, condition ConditionFunc) error {
  410. done := make(chan struct{})
  411. defer close(done)
  412. return PollUntil(interval, condition, done)
  413. }
  414. // PollImmediateInfinite tries a condition func until it returns true or an error
  415. //
  416. // PollImmediateInfinite runs the 'condition' before waiting for the interval.
  417. //
  418. // Some intervals may be missed if the condition takes too long or the time
  419. // window is too short.
  420. func PollImmediateInfinite(interval time.Duration, condition ConditionFunc) error {
  421. done, err := runConditionWithCrashProtection(condition)
  422. if err != nil {
  423. return err
  424. }
  425. if done {
  426. return nil
  427. }
  428. return PollInfinite(interval, condition)
  429. }
  430. // PollUntil tries a condition func until it returns true, an error or stopCh is
  431. // closed.
  432. //
  433. // PollUntil always waits interval before the first run of 'condition'.
  434. // 'condition' will always be invoked at least once.
  435. func PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error {
  436. ctx, cancel := contextForChannel(stopCh)
  437. defer cancel()
  438. return WaitFor(poller(interval, 0), condition, ctx.Done())
  439. }
  440. // PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed.
  441. //
  442. // PollImmediateUntil runs the 'condition' before waiting for the interval.
  443. // 'condition' will always be invoked at least once.
  444. func PollImmediateUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error {
  445. done, err := condition()
  446. if err != nil {
  447. return err
  448. }
  449. if done {
  450. return nil
  451. }
  452. select {
  453. case <-stopCh:
  454. return ErrWaitTimeout
  455. default:
  456. return PollUntil(interval, condition, stopCh)
  457. }
  458. }
  459. // WaitFunc creates a channel that receives an item every time a test
  460. // should be executed and is closed when the last test should be invoked.
  461. type WaitFunc func(done <-chan struct{}) <-chan struct{}
  462. // WaitFor continually checks 'fn' as driven by 'wait'.
  463. //
  464. // WaitFor gets a channel from 'wait()'', and then invokes 'fn' once for every value
  465. // placed on the channel and once more when the channel is closed. If the channel is closed
  466. // and 'fn' returns false without error, WaitFor returns ErrWaitTimeout.
  467. //
  468. // If 'fn' returns an error the loop ends and that error is returned. If
  469. // 'fn' returns true the loop ends and nil is returned.
  470. //
  471. // ErrWaitTimeout will be returned if the 'done' channel is closed without fn ever
  472. // returning true.
  473. //
  474. // When the done channel is closed, because the golang `select` statement is
  475. // "uniform pseudo-random", the `fn` might still run one or multiple time,
  476. // though eventually `WaitFor` will return.
  477. func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error {
  478. stopCh := make(chan struct{})
  479. defer close(stopCh)
  480. c := wait(stopCh)
  481. for {
  482. select {
  483. case _, open := <-c:
  484. ok, err := runConditionWithCrashProtection(fn)
  485. if err != nil {
  486. return err
  487. }
  488. if ok {
  489. return nil
  490. }
  491. if !open {
  492. return ErrWaitTimeout
  493. }
  494. case <-done:
  495. return ErrWaitTimeout
  496. }
  497. }
  498. }
  499. // poller returns a WaitFunc that will send to the channel every interval until
  500. // timeout has elapsed and then closes the channel.
  501. //
  502. // Over very short intervals you may receive no ticks before the channel is
  503. // closed. A timeout of 0 is interpreted as an infinity, and in such a case
  504. // it would be the caller's responsibility to close the done channel.
  505. // Failure to do so would result in a leaked goroutine.
  506. //
  507. // Output ticks are not buffered. If the channel is not ready to receive an
  508. // item, the tick is skipped.
  509. func poller(interval, timeout time.Duration) WaitFunc {
  510. return WaitFunc(func(done <-chan struct{}) <-chan struct{} {
  511. ch := make(chan struct{})
  512. go func() {
  513. defer close(ch)
  514. tick := time.NewTicker(interval)
  515. defer tick.Stop()
  516. var after <-chan time.Time
  517. if timeout != 0 {
  518. // time.After is more convenient, but it
  519. // potentially leaves timers around much longer
  520. // than necessary if we exit early.
  521. timer := time.NewTimer(timeout)
  522. after = timer.C
  523. defer timer.Stop()
  524. }
  525. for {
  526. select {
  527. case <-tick.C:
  528. // If the consumer isn't ready for this signal drop it and
  529. // check the other channels.
  530. select {
  531. case ch <- struct{}{}:
  532. default:
  533. }
  534. case <-after:
  535. return
  536. case <-done:
  537. return
  538. }
  539. }
  540. }()
  541. return ch
  542. })
  543. }
  544. // ExponentialBackoffWithContext works with a request context and a Backoff. It ensures that the retry wait never
  545. // exceeds the deadline specified by the request context.
  546. func ExponentialBackoffWithContext(ctx context.Context, backoff Backoff, condition ConditionFunc) error {
  547. for backoff.Steps > 0 {
  548. select {
  549. case <-ctx.Done():
  550. return ctx.Err()
  551. default:
  552. }
  553. if ok, err := runConditionWithCrashProtection(condition); err != nil || ok {
  554. return err
  555. }
  556. if backoff.Steps == 1 {
  557. break
  558. }
  559. waitBeforeRetry := backoff.Step()
  560. select {
  561. case <-ctx.Done():
  562. return ctx.Err()
  563. case <-time.After(waitBeforeRetry):
  564. }
  565. }
  566. return ErrWaitTimeout
  567. }