@@ -282,20 +282,44 @@ struct Clock {
282
282
base_instant : Instant ,
283
283
/// The amount of mock time which has elapsed.
284
284
elapsed_time : Duration ,
285
+
286
+ /// Reset every time the clock is advanced.
287
+ /// Decremented every time the clock is read.
288
+ /// If it reaches 0, we panic - otherwise code like
289
+ /// while Instant::now() < deadline { ... } will spin forever.
290
+ abort_counter : u32 ,
291
+ }
292
+
293
+ impl Clock {
294
+ const ABORT_COUNTER_START : u32 = 100_000_000 ;
295
+
296
+ #[ inline( always) ]
297
+ fn check_abort ( & mut self ) {
298
+ self . abort_counter -= 1 ;
299
+ if self . abort_counter == 0 {
300
+ panic ! ( "Likely infinite loop detected: clock sampled too many times without advancing" ) ;
301
+ }
302
+ }
303
+
304
+ #[ inline( always) ]
305
+ fn reset_abort_counter ( & mut self ) {
306
+ self . abort_counter = Self :: ABORT_COUNTER_START ;
307
+ }
285
308
}
286
309
287
310
impl ClockHandle {
288
311
const CLOCK_BASE : Duration = Duration :: from_secs ( 86400 ) ;
289
312
290
313
fn new ( base_time : SystemTime ) -> Self {
291
314
let base_instant: Instant = unsafe { std:: mem:: zeroed ( ) } ;
292
- let clock = Clock {
315
+ let mut clock = Clock {
293
316
base_time,
294
317
base_instant,
295
318
// Some code subtracts constant durations from Instant::now(), which underflows if the base
296
319
// instant is too small. That code is incorrect but we'll just make life easy anyway by
297
320
// starting the clock with one day of elapsed time.
298
321
elapsed_time : Self :: CLOCK_BASE ,
322
+ abort_counter : Clock :: ABORT_COUNTER_START ,
299
323
} ;
300
324
ClockHandle {
301
325
inner : Arc :: new ( Mutex :: new ( clock) ) ,
@@ -310,15 +334,18 @@ impl ClockHandle {
310
334
let mut inner = self . inner . lock ( ) . unwrap ( ) ;
311
335
// prevent time from going backwards - otherwise this can happen when timers are late.
312
336
inner. elapsed_time = std:: cmp:: max ( inner. elapsed_time , time) ;
337
+ inner. reset_abort_counter ( ) ;
313
338
}
314
339
315
340
fn elapsed ( & self ) -> Duration {
316
- let inner = self . inner . lock ( ) . unwrap ( ) ;
341
+ let mut inner = self . inner . lock ( ) . unwrap ( ) ;
342
+ inner. check_abort ( ) ;
317
343
inner. elapsed_time
318
344
}
319
345
320
346
fn advance ( & self , duration : Duration ) {
321
347
let mut inner = self . inner . lock ( ) . unwrap ( ) ;
348
+ inner. reset_abort_counter ( ) ;
322
349
inner. elapsed_time += duration;
323
350
}
324
351
@@ -328,12 +355,14 @@ impl ClockHandle {
328
355
}
329
356
330
357
fn now_instant ( & self ) -> Instant {
331
- let inner = self . inner . lock ( ) . unwrap ( ) ;
358
+ let mut inner = self . inner . lock ( ) . unwrap ( ) ;
359
+ inner. check_abort ( ) ;
332
360
inner. base_instant + inner. elapsed_time
333
361
}
334
362
335
363
fn now_time ( & self ) -> SystemTime {
336
- let inner = self . inner . lock ( ) . unwrap ( ) ;
364
+ let mut inner = self . inner . lock ( ) . unwrap ( ) ;
365
+ inner. check_abort ( ) ;
337
366
inner. base_time + inner. elapsed_time
338
367
}
339
368
}
0 commit comments