@@ -477,6 +477,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
477
477
if self . threads [ self . active_thread ] . check_terminated ( ) {
478
478
return Ok ( SchedulingAction :: ExecuteDtors ) ;
479
479
}
480
+ // If we get here again and the thread is *still* terminated, there are no more dtors to run.
480
481
if self . threads [ MAIN_THREAD ] . state == ThreadState :: Terminated {
481
482
// The main thread terminated; stop the program.
482
483
if self . threads . iter ( ) . any ( |thread| thread. state != ThreadState :: Terminated ) {
@@ -490,26 +491,25 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
490
491
}
491
492
return Ok ( SchedulingAction :: Stop ) ;
492
493
}
493
- // At least for `pthread_cond_timedwait` we need to report timeout when
494
- // the function is called already after the specified time even if a
495
- // signal is received before the thread gets scheduled. Therefore, we
496
- // need to schedule all timeout callbacks before we continue regular
497
- // execution.
498
- //
499
- // Documentation:
500
- // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
501
- let potential_sleep_time =
502
- self . timeout_callbacks . values ( ) . map ( |info| info. call_time . get_wait_time ( ) ) . min ( ) ;
503
- if potential_sleep_time == Some ( Duration :: new ( 0 , 0 ) ) {
504
- return Ok ( SchedulingAction :: ExecuteTimeoutCallback ) ;
505
- }
506
- // No callbacks scheduled, pick a regular thread to execute.
494
+ // This thread and the program can keep going.
507
495
if self . threads [ self . active_thread ] . state == ThreadState :: Enabled
508
496
&& !self . yield_active_thread
509
497
{
510
498
// The currently active thread is still enabled, just continue with it.
511
499
return Ok ( SchedulingAction :: ExecuteStep ) ;
512
500
}
501
+ // The active thread yielded. Let's see if there are any timeouts to take care of. We do
502
+ // this *before* running any other thread, to ensure that timeouts "in the past" fire before
503
+ // any other thread can take an action. This ensures that for `pthread_cond_timedwait`, "an
504
+ // error is returned if [...] the absolute time specified by abstime has already been passed
505
+ // at the time of the call".
506
+ // <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
507
+ let potential_sleep_time =
508
+ self . timeout_callbacks . values ( ) . map ( |info| info. call_time . get_wait_time ( ) ) . min ( ) ;
509
+ if potential_sleep_time == Some ( Duration :: new ( 0 , 0 ) ) {
510
+ return Ok ( SchedulingAction :: ExecuteTimeoutCallback ) ;
511
+ }
512
+ // No callbacks scheduled, pick a regular thread to execute.
513
513
// We need to pick a new thread for execution.
514
514
for ( id, thread) in self . threads . iter_enumerated ( ) {
515
515
if thread. state == ThreadState :: Enabled {
0 commit comments