Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a938df4
Update dcautil.c
Abhinavpv28 Jun 16, 2026
91620a6
Update dcautil.h
Abhinavpv28 Jun 16, 2026
c7dbcff
Update dcautil.h
Abhinavpv28 Jul 2, 2026
878e4bd
Update dcautil.c
Abhinavpv28 Jul 7, 2026
5078684
Potential fix for pull request finding
Abhinavpv28 Jul 13, 2026
ad31e4c
Potential fix for pull request finding 'CodeQL / File created without…
Abhinavpv28 Jul 13, 2026
e021963
Update dcautil.c
Abhinavpv28 Jul 13, 2026
50a344d
Update dcautil.h
Abhinavpv28 Jul 13, 2026
c9e25d1
Merge branch 'develop' into feature/RDKEMW-16716
Abhinavpv28 Jul 14, 2026
ebff0b3
Potential fix for pull request finding
Abhinavpv28 Jul 14, 2026
4865231
Update dcautil.c
Abhinavpv28 Jul 14, 2026
dbcd9cc
Fix formatting of error and info messages in dcautil.c
Abhinavpv28 Jul 14, 2026
0f107c3
Delete documentation comment for waitForBackupLogsDone
Abhinavpv28 Jul 14, 2026
72bdca5
Merge branch 'develop' into feature/RDKEMW-16716
Abhinavpv28 Jul 15, 2026
e8497e5
Update dcautil.c
Abhinavpv28 Jul 15, 2026
3d2470f
Update SystemMock.cpp
Abhinavpv28 Jul 15, 2026
65b3cf5
Update SystemMock.h
Abhinavpv28 Jul 15, 2026
dcfeff2
Update dcautil.c
Abhinavpv28 Jul 15, 2026
50b04eb
Update dcautil.c
Abhinavpv28 Jul 15, 2026
9d6bf4c
Update dcautil.c
Abhinavpv28 Jul 15, 2026
58106a9
Update dcautilTest.cpp
Abhinavpv28 Jul 15, 2026
aaacb42
Update L1-tests.yml
Abhinavpv28 Jul 15, 2026
3bfd046
Update L1-tests.yml
Abhinavpv28 Jul 15, 2026
e1e0867
Update dcautilTest.cpp
Abhinavpv28 Jul 15, 2026
ea1c091
Update SystemMock.h
Abhinavpv28 Jul 15, 2026
f1be148
Update SystemMock.cpp
Abhinavpv28 Jul 15, 2026
9970404
Update dcautilTest.cpp
Abhinavpv28 Jul 15, 2026
a352a62
Update L1-tests.yml
Abhinavpv28 Jul 15, 2026
8d0c205
Update dcautilTest.cpp
Abhinavpv28 Jul 15, 2026
d41909a
Update code-coverage.yml
Abhinavpv28 Jul 15, 2026
40151d8
Create test_backup_logs_sync.py
Abhinavpv28 Jul 15, 2026
1b99f39
L2
Jul 15, 2026
dc37887
Update test_backup_logs_sync.py
Abhinavpv28 Jul 15, 2026
0b4aebe
Delete test/functional-tests/tests/test_backup_logs_sync.py
Abhinavpv28 Jul 16, 2026
b8fbe70
Update code-coverage.yml
Abhinavpv28 Jul 17, 2026
eeea366
L1
aryany111 Jul 17, 2026
3145750
L1
aryany111 Jul 17, 2026
f4d2552
L!
aryany111 Jul 17, 2026
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
169 changes: 168 additions & 1 deletion source/dcautil/dcautil.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <sys/select.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "dca.h"
#include "dcautil.h"
#include "telemetry2_0.h"
Expand All @@ -28,6 +36,135 @@
#include "legacyutils.h"
#include "persistence.h"

/**
* @brief Wait for the backup_logs completion sentinel before grepping PreviousLogs.
*
* Strategy:
* 1. Fast path: sentinel already present → return true immediately.
* 2. Set up inotify on BACKUP_LOGS_DONE_DIR (/tmp) for IN_CREATE | IN_MOVED_TO.
* 3. Re-check after watch is established to close the creation race window.
* 4. select() loop with 2 s heartbeat; exit when sentinel appears or
* BACKUP_LOGS_SYNC_TIMEOUT_S total seconds have elapsed.
*
* This is a **soft gate**: if the function returns false (timeout or inotify
* failure) the caller still proceeds — previous-log grep runs against whatever
* files are present, and a warning is logged.
*
* @return true Sentinel detected within timeout
* @return false Timeout elapsed or sync could not be established (inotify/clock/select failure)
*/
bool waitForBackupLogsDone(void)
{
/* Fast path: sentinel already written by backup_logs */
if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0)
{
T2Info("backup_logs sentinel %s already present\n", BACKUP_LOGS_DONE_FLAG);
return true;
}

int ifd = inotify_init1(IN_CLOEXEC);
if (ifd < 0)
{
T2Error("inotify_init1 failed (errno=%d); proceeding without backup_logs sync\n", errno);
return false;
}

int wd = inotify_add_watch(ifd, BACKUP_LOGS_DONE_DIR, IN_CREATE | IN_MOVED_TO);
if (wd < 0)
{
T2Error("inotify_add_watch on %s failed (errno=%d); proceeding without backup_logs sync\n",
BACKUP_LOGS_DONE_DIR, errno);
close(ifd);
return false;
}

/* Re-check after watch is set — closes the race window between the first
* access() call and establishing the watch. */
if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0)
{
T2Info("backup_logs sentinel detected (race resolved): %s\n", BACKUP_LOGS_DONE_FLAG);
inotify_rm_watch(ifd, wd);
close(ifd);
return true;
}

struct timespec deadline;
if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0)
{
T2Error("clock_gettime failed (errno=%d); proceeding without backup_logs sync\n", errno);
inotify_rm_watch(ifd, wd);
close(ifd);
return false;
}
deadline.tv_sec += BACKUP_LOGS_SYNC_TIMEOUT_S;

T2Info("Waiting up to %ds for backup_logs sentinel: %s\n",
BACKUP_LOGS_SYNC_TIMEOUT_S, BACKUP_LOGS_DONE_FLAG);

bool found = false;
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];

while (!found)
{
/* Check deadline */
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC, &now) != 0)
{
T2Error("clock_gettime failed (errno=%d) while waiting for backup_logs sentinel; proceeding without sync\n", errno);
break;
}
if (now.tv_sec >= deadline.tv_sec)
{
T2Warning("backup_logs sentinel not present after %ds; proceeding without sync\n",
BACKUP_LOGS_SYNC_TIMEOUT_S);
break;
}
Comment thread
shibu-kv marked this conversation as resolved.

struct timeval tv = {2, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(ifd, &fds);

int ret = select(ifd + 1, &fds, NULL, NULL, &tv);
if (ret < 0)
{
if (errno == EINTR)
{
continue;
}
T2Error("select() failed (errno=%d) waiting for backup_logs sentinel\n", errno);
break;
}
if (ret == 0)
{
continue; /* 2 s heartbeat — loop back to check deadline */
}

ssize_t len = read(ifd, buf, sizeof(buf));
if (len <= 0)
{
continue;
}

ssize_t offset = 0;
while (offset < len)
{
struct inotify_event *ev = (struct inotify_event *)(buf + offset);
if (ev->len > 0 && strcmp(ev->name, BACKUP_LOGS_DONE_FILENAME) == 0)
{
T2Info("backup_logs sentinel created: %s\n", BACKUP_LOGS_DONE_FLAG);
found = true;
break;
}
offset += (ssize_t)(sizeof(struct inotify_event) + ev->len);
Comment thread
Abhinavpv28 marked this conversation as resolved.
}
Comment thread
Abhinavpv28 marked this conversation as resolved.
}

inotify_rm_watch(ifd, wd);
close(ifd);
return found;
}

/**
* @brief Get the Grep Results object. Main function called by rest of the consumers.
*
Expand All @@ -50,14 +187,44 @@ getGrepResults (GrepSeekProfile **GSP, Vector *markerList, bool isClearSeekMap,
return T2ERROR_FAILURE;
}

/* Synchronize with backup_logs before grepping the previous-log directory.
* backup_logs populates PREVIOUS_LOGS_PATH; reading it before the write is
* complete yields incomplete or empty results. This is a soft gate — if the
* sentinel does not appear within BACKUP_LOGS_SYNC_TIMEOUT_S seconds we
* still proceed so telemetry is never permanently blocked. */
if (customLogPath != NULL && strcmp(customLogPath, PREVIOUS_LOGS_PATH) == 0)
{
if (!waitForBackupLogsDone())
{
T2Warning("%s: backup_logs sentinel absent; grepping %s with potentially incomplete data\n",
__FUNCTION__, PREVIOUS_LOGS_PATH);
}
}
Comment thread
Abhinavpv28 marked this conversation as resolved.
Comment thread
Abhinavpv28 marked this conversation as resolved.

getDCAResultsInVector(*GSP, markerList, check_rotated, customLogPath);
if (isClearSeekMap)
{
int count = (*GSP)->execCounter;
freeGrepSeekProfile(*GSP);
*GSP = createGrepSeekProfile(count);
}

/* Signal that telemetry previous-log grep is complete.
* Downstream consumers (e.g. uploadSTBLogs) wait for this sentinel
* before starting the log upload to avoid incomplete telemetry data. */
Comment thread
Abhinavpv28 marked this conversation as resolved.
if (customLogPath != NULL && strcmp(customLogPath, PREVIOUS_LOGS_PATH) == 0)
{
int fd = open(TELEMETRY_PREVLOGS_DONE_FLAG, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd >= 0)
{
close(fd);
T2Info("Created telemetry previous-logs sentinel: %s\n", TELEMETRY_PREVLOGS_DONE_FLAG);
}
else
{
T2Error("%s: Failed to create sentinel %s (errno=%d)\n",
__FUNCTION__, TELEMETRY_PREVLOGS_DONE_FLAG, errno);
}
}
T2Debug("%s --out\n", __FUNCTION__);
return T2ERROR_SUCCESS;
}
Expand Down
12 changes: 11 additions & 1 deletion source/dcautil/dcautil.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,20 @@

#define TOPTEMP "/tmp/t2toplog"
#define DCADONEFLAG "/tmp/.dca_done"
#define TELEMETRY_PREVLOGS_DONE_FLAG "/tmp/.telemetry_prevlogs_done"

Comment thread
Abhinavpv28 marked this conversation as resolved.
#define PREVIOUS_LOG "PREVIOUS_LOG"
#define PREVIOUS_LOGS_VAL "1"
#define PREVIOUS_LOGS_PATH "/opt/logs/PreviousLogs/"
#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done"
#define BACKUP_LOGS_DONE_DIR "/tmp"
#define BACKUP_LOGS_DONE_FILENAME ".backup_logs_done"
Comment thread
Abhinavpv28 marked this conversation as resolved.

#ifdef GTEST_ENABLE
# define BACKUP_LOGS_SYNC_TIMEOUT_S 2
#else
# define BACKUP_LOGS_SYNC_TIMEOUT_S 60
#endif
Comment thread
Abhinavpv28 marked this conversation as resolved.

typedef struct _GrepResult
{
Expand Down Expand Up @@ -79,7 +89,7 @@ int getMemInfo(procMemCpuInfo *pmInfo);
int getCPUInfo(procMemCpuInfo *pInfo, char* filename);
int getProcPidStat(int pid, procinfo * pinfo);
int getTotalCpuTimes(int * totalTime);

bool waitForBackupLogsDone(void);

#ifdef PERSIST_LOG_MON_REF
typedef void (*freeconfigdata)(void *data);
Expand Down
Loading
Loading