Skip to content
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,22 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [1.11.0](https://github.com/rdkcentral/telemetry/compare/1.10.4...1.11.0)

- TCXB7-7251: Fix marker loss on in-place log truncation [`#445`](https://github.com/rdkcentral/telemetry/pull/445)
- 62336: Fix Coverity defects (1 file) [`#433`](https://github.com/rdkcentral/telemetry/pull/433)
- RDKB-62334: Fix Coverity defects (1 file) [`#436`](https://github.com/rdkcentral/telemetry/pull/436)
- 62335 :Fix scheduler profile teardown wait for CID-56336 [`#444`](https://github.com/rdkcentral/telemetry/pull/444)
- RDK-62333: Fix Coverity defects [`#443`](https://github.com/rdkcentral/telemetry/pull/443)
- RDKEMW-test: Fix Coverity defects for RESOURCE_LEAK - CID-51128 and CID-51137 [`#427`](https://github.com/rdkcentral/telemetry/pull/427)
- RDKB-64502: [RDKB][TELEMETRY2_0] Multi‑profile config using method = subscribe, logs null & empty values [`#406`](https://github.com/rdkcentral/telemetry/pull/406)

#### [1.10.4](https://github.com/rdkcentral/telemetry/compare/1.10.3...1.10.4)

> 10 September 2026

- RDKB-66418: Handle rbus method failure efficiently [`#423`](https://github.com/rdkcentral/telemetry/pull/423)
- Changelog updates for 1.10.4 release [`7a92306`](https://github.com/rdkcentral/telemetry/commit/7a923068c2e863ba96633d8c5b615296c18d560b)

#### [1.10.3](https://github.com/rdkcentral/telemetry/compare/1.10.2...1.10.3)

Expand Down
122 changes: 104 additions & 18 deletions source/bulkdata/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ typedef struct __triggerConditionObj__
char referenceValue[MAX_LEN];
} triggerConditionObj ;

static bool isEmptySubscriberValue(const char *value)
{
if(value == NULL)
{
return true;
}
if(strlen(value) < 1 || value[0] == ' ' || strncmp(value, "NULL", 4) == 0)
{
return true;
}
return false;
}

static void freeRequestURIparam(void *data)
{
if(data != NULL)
Expand Down Expand Up @@ -233,6 +246,10 @@ void freeProfile(void *data)
cJSON_Delete(profile->jsonReportObj);
profile->jsonReportObj = NULL;
}
if(profile->grepSeekProfile)
{
freeGrepSeekProfile(profile->grepSeekProfile);
}
free(profile);
}
T2Debug("%s ++out \n", __FUNCTION__);
Expand Down Expand Up @@ -969,6 +986,7 @@ reportThreadEnd :
pthread_mutex_lock(&profile->reuseThreadMutex);
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
profile->reportThreadCreated = false;
pthread_cond_signal(&profile->reportInProgressCond);
pthread_mutex_unlock(&profile->reportInProgressMutex);
pthread_mutex_unlock(&profile->reuseThreadMutex);
Expand Down Expand Up @@ -1018,7 +1036,20 @@ void NotifyTimeout(const char* profileName, bool isClearSeekMap)
else
{
pthread_mutex_unlock(&profile->reuseThreadMutex);
pthread_create(&profile->reportThread, NULL, CollectAndReport, (void*)profile);
int createStatus = pthread_create(&profile->reportThread, NULL, CollectAndReport, (void*)profile);
pthread_mutex_lock(&profile->reportInProgressMutex);
if(createStatus == 0 && profile->reportInProgress)
{
profile->reportThreadCreated = true;
}
else
{
profile->reportInProgress = false;
profile->reportThreadCreated = false;
Comment on lines +1039 to +1048
pthread_cond_signal(&profile->reportInProgressCond);
T2Error("Failed to create report thread for profile %s: %d\n", profileName, createStatus);
}
pthread_mutex_unlock(&profile->reportInProgressMutex);
}
}
else
Expand Down Expand Up @@ -1098,12 +1129,19 @@ T2ERROR Profile_storeMarkerEvent(const char *profileName, T2Event *eventInfo)
break;

case MTYPE_ACCUMULATE:
T2Debug("Marker type is ACCUMULATE Event Value : %s\n", eventInfo->value);
{
const char *safeValue = (eventInfo->value != NULL) ? eventInfo->value : "";
T2Debug("Marker type is ACCUMULATE Event Value : %s\n", safeValue);
if(!lookupEvent->reportEmptyParam && isEmptySubscriberValue(safeValue))
{
T2Debug("Skipping empty/null subscribe marker value for %s\n", lookupEvent->markerName);
break;
Comment on lines +1133 to +1138
}
arraySize = Vector_Size(lookupEvent->u.accumulatedValues);
T2Debug("Current array size : %d \n", arraySize);
if( arraySize < MAX_ACCUMULATE)
{
Vector_PushBack(lookupEvent->u.accumulatedValues, strdup(eventInfo->value));
Vector_PushBack(lookupEvent->u.accumulatedValues, strdup(safeValue));
T2Debug("Sucessfully added value into vector New Size : %d\n", ++arraySize);
if(lookupEvent->reportTimestampParam == REPORTTIMESTAMP_UNIXEPOCH)
{
Expand Down Expand Up @@ -1137,16 +1175,24 @@ T2ERROR Profile_storeMarkerEvent(const char *profileName, T2Event *eventInfo)
T2Warning("Max size of the array has been reached Ignore New Value\n");
}
break;
}

case MTYPE_ABSOLUTE:
default:
{
const char *safeValue = (eventInfo->value != NULL) ? eventInfo->value : "";
if(!lookupEvent->reportEmptyParam && isEmptySubscriberValue(safeValue))
{
T2Debug("Skipping empty/null subscribe marker value for %s\n", lookupEvent->markerName);
break;
}
if(lookupEvent->u.markerValue)
{
free(lookupEvent->u.markerValue);
lookupEvent->u.markerValue = NULL;
}

lookupEvent->u.markerValue = strdup(eventInfo->value);
lookupEvent->u.markerValue = strdup(safeValue);
T2Debug("New marker value saved : %s\n", lookupEvent->u.markerValue);
if(lookupEvent->reportTimestampParam == REPORTTIMESTAMP_UNIXEPOCH)
{
Expand Down Expand Up @@ -1175,6 +1221,7 @@ T2ERROR Profile_storeMarkerEvent(const char *profileName, T2Event *eventInfo)
}
break;
}
}
pthread_mutex_unlock(&profile->eventMutex);
}
else
Expand Down Expand Up @@ -1416,13 +1463,6 @@ T2ERROR deleteAllProfiles(bool delFromDisk)
* after setting threadExists = false (see CollectAndReport cleanup). */
}

/* grepSeekProfile cleanup is safe without profileListLock here:
* the profile's thread has been joined (or never existed), and
* initialized=false prevents concurrent access from other threads. */
if(tempProfile->grepSeekProfile)
{
freeGrepSeekProfile(tempProfile->grepSeekProfile);
}
if(delFromDisk == true)
{
removeProfileFromDisk(REPORTPROFILES_PERSISTENCE_PATH, tempProfile->name);
Expand Down Expand Up @@ -1548,11 +1588,6 @@ T2ERROR deleteProfile(const char *profileName)
rbusT2ConsumerUnReg(profile->triggerConditionList);
}

if(profile->grepSeekProfile)
{
freeGrepSeekProfile(profile->grepSeekProfile);
}

pthread_mutex_destroy(&profile->reportInProgressMutex);
pthread_cond_destroy(&profile->reportInProgressCond);

Expand Down Expand Up @@ -1953,6 +1988,7 @@ T2ERROR appendTriggerCondition (Profile *tempProfile, const char *referenceName,
else
{
T2Warning("%s : referenceName or referenceValue is published as null, ignoring trigger condition \n ", __FUNCTION__);
free(triggerCond);
}

}
Expand Down Expand Up @@ -2062,6 +2098,19 @@ T2ERROR triggerReportOnCondtion(const char *referenceName, const char *reference
tempProfile->callBackOnReportGenerationComplete = reportGenerationCompleteReceiver;

char *tempProfilename = strdup(tempProfile->name); //RDKB-42640
if(tempProfilename == NULL)
{
T2Error("Failed to allocate profile name while triggering report condition\n");
if(tempProfile->jsonReportObj != NULL)
{
cJSON_Delete(tempProfile->jsonReportObj);
tempProfile->jsonReportObj = NULL;
}
tempProfile->triggerReportOnCondition = false;
pthread_mutex_unlock(&tempProfile->triggerCondMutex);
pthread_rwlock_unlock(&profileListLock);
return T2ERROR_FAILURE;
}

// profileListLock should be unlocked before sending interrupt for report generation
T2Debug("%s : Release lock on &profileListLock\n ", __FUNCTION__);
Expand All @@ -2070,8 +2119,29 @@ T2ERROR triggerReportOnCondtion(const char *referenceName, const char *reference
triggerCondition->oprator, triggerCondition->threshold);
if(tempProfile->isSchedulerstarted)
{
SendInterruptToTimeoutThread(tempProfilename, false);
// triggerCondMutex will be unlocked by CollectAndReport after report generation
T2ERROR sendRet = SendInterruptToTimeoutThread(tempProfilename, false);
if(sendRet != T2ERROR_SUCCESS)
{
bool workerOwnsTrigger = false;
pthread_mutex_lock(&tempProfile->reportInProgressMutex);
workerOwnsTrigger = tempProfile->reportInProgress && tempProfile->reportThreadCreated;
if(!workerOwnsTrigger)
{
tempProfile->triggerReportOnCondition = false;
}
pthread_mutex_unlock(&tempProfile->reportInProgressMutex);

if(!workerOwnsTrigger)
{
T2Info("For Profile %s SendInterruptToTimeoutThread failed, releasing lock\n", tempProfilename);
pthread_mutex_unlock(&tempProfile->triggerCondMutex);
if(tempProfile->callBackOnReportGenerationComplete)
{
tempProfile->callBackOnReportGenerationComplete(tempProfilename);
}
}
}
// On success: triggerCondMutex will be unlocked by CollectAndReport after report generation
}
else
{
Expand Down Expand Up @@ -2100,6 +2170,22 @@ T2ERROR triggerReportOnCondtion(const char *referenceName, const char *reference
return T2ERROR_SUCCESS;
}

#ifdef GTEST_ENABLE
void test_set_profile_list(Vector *testProfileList)
{
profileList = testProfileList;
initialized = true;
pthread_rwlock_init(&profileListLock, NULL);
}

void test_reset_profile_list(void)
{
initialized = false;
profileList = NULL;
pthread_rwlock_destroy(&profileListLock);
}
#endif

unsigned int getMinThresholdDuration(char *profileName)
{
unsigned int minThresholdDuration = 0;
Expand Down
1 change: 1 addition & 0 deletions source/bulkdata/profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ typedef struct _Profile
pthread_mutex_t reuseThreadMutex;
bool restartRequested;
bool threadExists;
bool reportThreadCreated;
GrepSeekProfile *grepSeekProfile; // To store GrepConfig
} Profile;

Expand Down
Loading
Loading