Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 133 additions & 4 deletions systimemgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#endif

#include "systimerfactory/networkstatussrc.h"
#include <sys/timex.h>
#include <fcntl.h>


#ifdef T2_EVENT_ENABLED
#include <telemetry_busmessage_sender.h>
Expand Down Expand Up @@ -197,11 +200,13 @@ void SysTimeMgr::run(bool forever)
: "not found, skipping network event threads");
std::thread nwEventProcessThrd;
std::thread nwEventSubscribeThrd;
std::thread ntpSyncMonitorThrd;
if (chronyRfcEnabled) {
/* nwEventProcessThrd must start before nwEventSubscribeThrd so the
* processing thread is ready before any event can arrive. */
nwEventProcessThrd = std::thread(SysTimeMgr::nwEventProcessThr, this);
nwEventSubscribeThrd = std::thread(SysTimeMgr::nwEventSubscribeThr, this);
ntpSyncMonitorThrd = std::thread(SysTimeMgr::ntpSyncMonitorThr,this);
}

if (forever)
Expand All @@ -215,20 +220,31 @@ void SysTimeMgr::run(bool forever)
processThrd.join();
timerThrd.join();
pathMonitorThrd.join();
if (nwEventProcessThrd.joinable())
if (nwEventProcessThrd.joinable()) {
nwEventProcessThrd.join();
if (nwEventSubscribeThrd.joinable())
}
if (nwEventSubscribeThrd.joinable()) {
nwEventSubscribeThrd.join();
}
if (ntpSyncMonitorThrd.joinable()) {
ntpSyncMonitorThrd.join();
}

}
else
{
processThrd.detach();
timerThrd.detach();
pathMonitorThrd.detach();
if (nwEventProcessThrd.joinable())
if (nwEventProcessThrd.joinable()) {
nwEventProcessThrd.detach();
if (nwEventSubscribeThrd.joinable())
}
if (nwEventSubscribeThrd.joinable()) {
nwEventSubscribeThrd.detach();
}
if (ntpSyncMonitorThrd.joinable()) {
ntpSyncMonitorThrd.detach();
}
}
}

Expand Down Expand Up @@ -269,6 +285,119 @@ void SysTimeMgr::nwEventProcessThr(SysTimeMgr* instance)
instance->runNWEventProcessing();
}

void SysTimeMgr::ntpSyncMonitorThr(SysTimeMgr* instance)
{
if (instance)
instance->runNTPSyncMonitor();
}

/*
* runNTPSyncMonitor: polls adjtimex() once per second until the kernel clock is
* synchronised with NTP (STA_UNSYNC flag cleared). On success it logs the
* event, creates /tmp/clock-event and /tmp/systimemgr/ntp, then returns.
* The primary purpose is to capture the NTP convergence time.
Comment thread
sindhu-krishnan marked this conversation as resolved.
*/
void SysTimeMgr::runNTPSyncMonitor()
{
RDK_LOG(RDK_LOG_INFO, LOG_SYSTIME,
"[%s:%d]: CHRONY: NTP sync monitor thread started\n", __FUNCTION__, __LINE__);

Comment thread
sindhu-krishnan marked this conversation as resolved.
while (1)
Comment thread
sindhu-krishnan marked this conversation as resolved.
{
struct timex tx;
memset(&tx, 0, sizeof(tx));

/* Capture adjtimex() return value: TIME_ERROR means the kernel clock
* is not disciplined, which is treated the same as STA_UNSYNC. */
int adjtimex_state = adjtimex(&tx);
if (adjtimex_state < 0)
{
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: CHRONY: adjtimex() failed, retrying\n", __FUNCTION__, __LINE__);
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}

if (adjtimex_state == TIME_ERROR || (tx.status & STA_UNSYNC))
{
/* Clock not yet synchronised — keep polling. */
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}
Comment thread
sindhu-krishnan marked this conversation as resolved.

/* NTP synchronisation achieved. */
RDK_LOG(RDK_LOG_INFO, LOG_SYSTIME,
"[%s:%d]: CHRONY: NTP synchronised\n", __FUNCTION__, __LINE__);

/* Create /tmp/systimemgr/ntp and update its timestamps via futimens()
* so that the inotify IN_ATTRIB event fires and the path monitor thread
* reliably dispatches eSYSMGR_EVENT_NTP_AVAILABLE into the state machine.
* O_NOFOLLOW|O_CLOEXEC guard against symlink attacks. */
{
int fd = open((m_directory + "/ntp").c_str(),
O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, 0644);
if (fd >= 0)
{
struct timespec ts[2];
timespec_get(&ts[0], TIME_UTC);
ts[1] = ts[0];
if (futimens(fd, ts) != 0)
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: futimens() failed for %s/ntp\n",
__FUNCTION__, __LINE__, m_directory.c_str());
close(fd);
}
else
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: Failed to create %s/ntp\n",
__FUNCTION__, __LINE__, m_directory.c_str());
}

/* Create /tmp/clock-event — O_NOFOLLOW|O_CLOEXEC guard against
* symlink/hardlink attacks when running with elevated privileges. */
Comment thread
sindhu-krishnan marked this conversation as resolved.
{
int fd = open("/tmp/clock-event",
O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0644);
if (fd >= 0)
Comment thread
sindhu-krishnan marked this conversation as resolved.
close(fd);
else
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: Failed to create /tmp/clock-event\n",
__FUNCTION__, __LINE__);
}

/* Write NTP sync status to /tmp/ntp_status — O_NOFOLLOW|O_CLOEXEC
* guards against symlink attacks; write() return value is checked. */
{
int fd = open("/tmp/ntp_status",
O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0644);
if (fd >= 0)
{
const char* status = "Synchronized\n";
ssize_t written = write(fd, status, strlen(status));
if (written < 0)
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: Failed to write to /tmp/ntp_status\n",
Comment thread
sindhu-krishnan marked this conversation as resolved.
__FUNCTION__, __LINE__);
Comment thread
sindhu-krishnan marked this conversation as resolved.
close(fd);
}
else
{
RDK_LOG(RDK_LOG_ERROR, LOG_SYSTIME,
"[%s:%d]: Failed to create /tmp/ntp_status\n",
__FUNCTION__, __LINE__);
}
}

/* Synchronisation captured — stop polling. */
break;
}


RDK_LOG(RDK_LOG_INFO, LOG_SYSTIME,
"[%s:%d]: CHRONY: NTP sync monitor thread exiting\n", __FUNCTION__, __LINE__);
}


void SysTimeMgr::processMsg()
{
Expand Down
2 changes: 2 additions & 0 deletions systimemgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,12 @@ class SysTimeMgr
static void pathThr(SysTimeMgr* instance);
static void nwEventSubscribeThr(SysTimeMgr* instance);
static void nwEventProcessThr(SysTimeMgr* instance);
static void ntpSyncMonitorThr(SysTimeMgr* instance);


void runNetworkStatusMonitor();
void runNWEventProcessing();
void runNTPSyncMonitor();

void updateTimeSync(long long updateTime);
void publishStatus(publishEvent event,string message);
Expand Down
Loading