Skip to content

Commit 4946111

Browse files
authored
Bugfix: Update state machine to use monotonic time for delay enforcement (#46)
This fixes error: "invalid execution delay error". This could occur after NTP clock adjustments causing system clock to jump backwards.
1 parent d7e9479 commit 4946111

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

Implementation/Common/common_chrono.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ namespace AMCCommon {
187187
return convertToISO8601TimeUTC(getUTCTimeStampInMicrosecondsSince1970());
188188
}
189189

190+
uint64_t CChrono::getElapsedMicroseconds()
191+
{
192+
return m_pChronoImpl->getElapsedMicroseconds();
193+
}
194+
190195
void CChrono::sleepSeconds(const uint64_t seconds)
191196
{
192197
sleepMicroseconds(seconds * 1000000ULL);

Implementation/Common/common_chrono.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ namespace AMCCommon {
6868
// Returns Absolute UTC Time Stamp in ISO8601 formatting
6969
std::string getUTCTimeInISO8601();
7070

71+
// Returns Monotonic Elapsed Time in microseconds since instance creation
72+
// This time is NOT affected by system clock adjustments (NTP, manual changes)
73+
// Use this for timing and delays, NOT for absolute timestamps
74+
uint64_t getElapsedMicroseconds();
75+
7176
// Sleeps for some seconds
7277
static void sleepSeconds(const uint64_t seconds);
7378

Implementation/Core/amc_statemachinestate.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ namespace AMC {
8585

8686
void CStateMachineState::updateExecutionTime()
8787
{
88-
m_LastExecutionTimeStampInMicroseconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970 ();
88+
// Use monotonic elapsed time to avoid issues with NTP clock adjustments
89+
m_LastExecutionTimeStampInMicroseconds = m_pGlobalChrono->getElapsedMicroseconds();
8990
}
9091

9192

@@ -161,8 +162,9 @@ namespace AMC {
161162

162163
if (chunkInMilliseconds < AMC_MINREPEATDELAY_MS)
163164
throw ELibMCCustomException(LIBMC_ERROR_INVALIDREPEATDELAY, m_sInstanceName);
164-
165-
uint64_t executionTimeInMicroSeconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970();
165+
166+
// Use monotonic elapsed time - not affected by NTP or system clock adjustments
167+
uint64_t executionTimeInMicroSeconds = m_pGlobalChrono->getElapsedMicroseconds();
166168
if (m_LastExecutionTimeStampInMicroseconds > executionTimeInMicroSeconds)
167169
throw ELibMCCustomException(LIBMC_ERROR_INVALIDEXECUTIONDELAY, std::to_string (m_LastExecutionTimeStampInMicroseconds));
168170

@@ -171,7 +173,7 @@ namespace AMC {
171173
while (deltaExecutionTimeInMicroSeconds < (m_nRepeatDelay * 1000ULL)) {
172174
m_pGlobalChrono->sleepMilliseconds(chunkInMilliseconds);
173175

174-
uint64_t newExecutionTimeInMicroSeconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970();
176+
uint64_t newExecutionTimeInMicroSeconds = m_pGlobalChrono->getElapsedMicroseconds();
175177
if (m_LastExecutionTimeStampInMicroseconds > newExecutionTimeInMicroSeconds)
176178
throw ELibMCCustomException(LIBMC_ERROR_INVALIDEXECUTIONDELAY, std::to_string(m_LastExecutionTimeStampInMicroseconds));
177179

0 commit comments

Comments
 (0)