-
Notifications
You must be signed in to change notification settings - Fork 10k
Open
Description
Describe the bug
Time jumps when using a timer can cause the thread sleep duration to be incorrect.
To Reproduce
Steps to reproduce the behavior:
- start cyber timer or timer_component
- date -s xxxx-xx-xx(not now)
- Monitor the execution of the timer task
- The timer task is no longer executed
Expected behavior
Timer execution is not affected by time jumps
Additional context
timing wheel use Rate Sleep fun :
void TimingWheel::TickFunc() {
Rate rate(TIMER_RESOLUTION_MS * 1000000); // ms to ns
while (running_) {
Tick();
// AINFO_EVERY(1000) << "Tick " << TickCount();
tick_count_++;
rate.Sleep();
{
std::lock_guard<std::mutex> lock(current_work_wheel_index_mutex_);
current_work_wheel_index_ =
GetWorkWheelIndex(current_work_wheel_index_ + 1);
}
if (current_work_wheel_index_ == 0) {
{
std::lock_guard<std::mutex> lock(current_assistant_wheel_index_mutex_);
current_assistant_wheel_index_ =
GetAssistantWheelIndex(current_assistant_wheel_index_ + 1);
}
Cascade(current_assistant_wheel_index_);
}
}
}and Rate::Sleep used Time::SleepUntil perform thread sleep operation
void Rate::Sleep() {
Time expected_end = start_ + expected_cycle_time_;
Time actual_end = Time::Now();
// detect backward jumps in time
if (actual_end < start_) {
AWARN << "Detect backward jumps in time";
expected_end = actual_end + expected_cycle_time_;
}
// calculate the time we'll sleep for
Duration sleep_time = expected_end - actual_end;
// set the actual amount of time the loop took in case the user wants to kNow
actual_cycle_time_ = actual_end - start_;
// make sure to reset our start time
start_ = expected_end;
// if we've taken too much time we won't sleep
if (sleep_time < Duration(0.0)) {
AWARN << "Detect forward jumps in time";
// if we've jumped forward in time, or the loop has taken more than a full
// extra cycle, reset our cycle
if (actual_end > expected_end + expected_cycle_time_) {
start_ = actual_end;
}
// return false to show that the desired rate was not met
return;
}
Time::SleepUntil(expected_end);
}but, Time::SleepUntil use system_clock, When a system time jump occurs, the sleep time may be calculated incorrectly.
void Time::SleepUntil(const Time& time) {
auto nano = std::chrono::nanoseconds(time.ToNanosecond());
system_clock::time_point tp(nano);
std::this_thread::sleep_until(tp);
}Why Rate not use steady_clock replace system_clock, and use Time::MonoTime() replace 'Time::Now()'
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels