diff --git a/platforms/posix/src/lockstep_scheduler/include/lockstep_scheduler/lockstep_scheduler.h b/platforms/posix/src/lockstep_scheduler/include/lockstep_scheduler/lockstep_scheduler.h index 10c084aa4b..d9c8c6daee 100644 --- a/platforms/posix/src/lockstep_scheduler/include/lockstep_scheduler/lockstep_scheduler.h +++ b/platforms/posix/src/lockstep_scheduler/include/lockstep_scheduler/lockstep_scheduler.h @@ -21,6 +21,18 @@ private: struct TimedWait { ~TimedWait() { + if (!done) { + // This can only happen when a thread gets canceled (e.g. via pthread_cancel), and since + // pthread_cond_wait is a cancellation point, the rest of LockstepScheduler::cond_timedwait afterwards + // might not be executed. Which means the mutex will not be unlocked either, so we unlock to avoid + // a dead-lock in LockstepScheduler::set_absolute_time(). + // This destructor gets called as part of thread-local storage cleanup. + // This is really only a work-around for non-proper thread stopping. Note that we also assume, + // that we can still access the mutex. + pthread_mutex_unlock(passed_lock); + done = true; + } + // If a thread quickly exits after a cond_timedwait(), the // thread_local object can still be in the linked list. In that case // we need to wait until it's removed.