Skip to content

Conversation

@madhubabutt
Copy link
Contributor

No description provided.

@madhubabutt madhubabutt requested a review from a team as a code owner January 2, 2026 08:41
@madhubabutt madhubabutt force-pushed the feature/RDK-60291 branch 3 times, most recently from 15ccf65 to b9475ed Compare January 8, 2026 06:13
@rdkcmf-jenkins
Copy link
Contributor

rdkcmf-jenkins commented Jan 8, 2026

Coverity Issue - Data race condition

A wait is performed without a loop. If there is a spurious wakeup, the condition may not be satisfied.

Medium Impact, CWE-none
BAD_CHECK_OF_WAIT_COND

How to fix

Check the wait condition in a loop, with the lock held. The lock must not be released between the condition and the wait.

Issue location

This issue was discovered outside the diff for this Pull Request. You can find it at:
source/bulkdata/profile.c:849

// Release reuseThreadMutex before acquiring reportInProgressMutex to maintain lock order
pthread_mutex_unlock(&profile->reuseThreadMutex);
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = true;
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

pthread_mutex_lock(&xcThreadMutex);
stopFetchRemoteConfiguration = true;
T2Debug("%s while Loop -- END; wait for restart event\n", __FUNCTION__);
pthread_cond_wait(&xcThreadCond, &xcThreadMutex);
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Data race condition

A wait is performed without a loop. If there is a spurious wakeup, the condition may not be satisfied.

Medium Impact, CWE-none
BAD_CHECK_OF_WAIT_COND

How to fix

Check the wait condition in a loop, with the lock held. The lock must not be released between the condition and the wait.

Copilot AI review requested due to automatic review settings January 13, 2026 06:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request addresses Coverity static analysis defects in the telemetry Device Management component, focusing on improving thread safety, error handling, and security practices.

Changes:

  • Enhanced thread synchronization with proper mutex lock/unlock patterns and condition variable handling
  • Added error checking for system calls (write, stat, fread, system) with appropriate error logging
  • Fixed potential memory leaks in realloc usage by using temporary pointers
  • Improved integer overflow protection when converting uint32_t to int
  • Enhanced security by setting secure umask before mkstemp calls
  • Replaced insecure rand() with /dev/urandom for better random number generation

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 28 comments.

Show a summary per file
File Description
source/xconf-client/xconfclient.c Improved mutex locking patterns for thread safety, added error handling for pipe write operations
source/utils/t2collection.c Fixed potential integer underflow by checking for zero count before subtraction
source/utils/persistence.c Added error checking for stat and fread system calls
source/scheduler/scheduler.c Enhanced thread termination logic and improved mutex handling around sleep operations
source/reportgen/reportgen.c Fixed potential memory leak in realloc by using temporary pointer
source/protocol/rbusMethod/rbusmethodinterface.c Added missing mutex lock for thread-safe access to shared variable
source/dcautil/dca.c Implemented secure temporary file creation with restrictive umask
source/commonlib/telemetry_busmessage_sender.c Added null pointer check before string operations and proper variable initialization
source/bulkdata/t2eventreceiver.c Improved thread synchronization and condition variable handling
source/bulkdata/reportprofiles.c Added integer overflow protection when converting hashmap count to signed int
source/bulkdata/profile.c Fixed lock ordering to prevent deadlocks and replaced rand() with /dev/urandom
source/bulkdata/datamodel.c Enhanced thread safety with improved condition variable and mutex handling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1330 to 1332
do {
n = pthread_cond_timedwait(&xcCond, &xcMutex, &_ts);
} while(n != ETIMEDOUT && n != 0);
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do-while loop here will continue retrying even after pthread_cond_timedwait succeeds (returns 0). This breaks the intended behavior where the thread should wake up when signaled via pthread_cond_signal. The loop should only retry on spurious wakeups (when the return value is neither ETIMEDOUT nor 0), not when the call succeeds. Consider using while(n != ETIMEDOUT && n != 0 && n == EINTR) if you only want to handle spurious wakeups, or remove this do-while wrapper if spurious wakeup handling isn't necessary.

Copilot uses AI. Check for mistakes.
Comment on lines 1339 to 1353
hashmap_count = hash_map_count(profileHashMap);
if (hashmap_count == 0 || hashmap_count == UINT32_MAX)
{
count = -1;
}
else
{
count = (int)(hashmap_count - 1);
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for hashmap_count == UINT32_MAX is checking for an edge case that is unlikely to occur in practice and may not be the correct way to detect an error from hash_map_count. If hash_map_count returns UINT32_MAX to indicate an error (which would be unusual), this should be documented or verified. More importantly, when hashmap_count == 0, setting count = -1 is correct for the while loop condition while(count >= 0) to immediately exit, but the check should ensure this is the intended behavior. Consider adding a comment explaining why UINT32_MAX is checked.

Copilot uses AI. Check for mistakes.
break;
}

if( clock_gettime(CLOCK_MONOTONIC, &_now) == -1 )
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation here. The line uses a tab character instead of spaces. This should be indented with spaces to match the project's coding style.

Suggested change
if( clock_gettime(CLOCK_MONOTONIC, &_now) == -1 )
if( clock_gettime(CLOCK_MONOTONIC, &_now) == -1 )

Copilot uses AI. Check for mistakes.
Comment on lines 666 to 680

// Unlock scMutex before sleeping to avoid holding lock during sleep
if(pthread_mutex_unlock(&scMutex) != 0)
{
T2Error("scMutex unlock failed\n");
return T2ERROR_FAILURE;
}

int count = 0;
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation here. Lines 666-674 use tab characters instead of spaces. This should be indented with spaces to match the project's coding style.

Suggested change
// Unlock scMutex before sleeping to avoid holding lock during sleep
if(pthread_mutex_unlock(&scMutex) != 0)
{
T2Error("scMutex unlock failed\n");
return T2ERROR_FAILURE;
}
int count = 0;
// Unlock scMutex before sleeping to avoid holding lock during sleep
if(pthread_mutex_unlock(&scMutex) != 0)
{
T2Error("scMutex unlock failed\n");
return T2ERROR_FAILURE;
}
int count = 0;

Copilot uses AI. Check for mistakes.
ret = report_or_cache_data(strvalue, marker);
if(strvalue != NULL)
{
{
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are trailing whitespace characters at the end of this line. Trailing whitespace should be removed to maintain code cleanliness.

Suggested change
{
{

Copilot uses AI. Check for mistakes.
Comment on lines 287 to 289
do {
n = pthread_cond_timedwait(&tProfile->tCond, &tProfile->tMutex, &_ts);
} while(n != ETIMEDOUT && n != 0);
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do-while loop here will continue retrying even after pthread_cond_timedwait succeeds (returns 0). This breaks the intended behavior where the thread should wake up when signaled via pthread_cond_signal. The loop should only retry on spurious wakeups (when the return value is neither ETIMEDOUT nor 0), not when the call succeeds. Consider using while(n != ETIMEDOUT && n != 0 && n == EINTR) if you only want to handle spurious wakeups, or remove this do-while wrapper if spurious wakeup handling isn't necessary.

Copilot uses AI. Check for mistakes.
n = pthread_cond_timedwait(&profile->reportcond, &profile->reportMutex, &profile->maxlatencyTime);
do {
n = pthread_cond_timedwait(&profile->reportcond, &profile->reportMutex, &profile->maxlatencyTime);
} while(n != ETIMEDOUT && n != 0);
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do-while loop here will continue retrying even after pthread_cond_timedwait succeeds (returns 0). This breaks the intended behavior where the thread should wake up when signaled via pthread_cond_signal. The loop should only retry on spurious wakeups (when the return value is neither ETIMEDOUT nor 0), not when the call succeeds. Consider using while(n != ETIMEDOUT && n != 0 && n == EINTR) if you only want to handle spurious wakeups, or remove this do-while wrapper if spurious wakeup handling isn't necessary.

Suggested change
} while(n != ETIMEDOUT && n != 0);
} while (n == EINTR);

Copilot uses AI. Check for mistakes.
stopFetchRemoteConfiguration = false;
pthread_cond_signal(&xcThreadCond);
pthread_mutex_unlock(&xcThreadMutex);
//pthread_create(&xcrThread, NULL, getUpdatedConfigurationThread, NULL);
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation here. The line uses a tab character instead of spaces. This should be indented with spaces to match the project's coding style.

Suggested change
//pthread_create(&xcrThread, NULL, getUpdatedConfigurationThread, NULL);
//pthread_create(&xcrThread, NULL, getUpdatedConfigurationThread, NULL);

Copilot uses AI. Check for mistakes.
Comment on lines 208 to 214
bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
{
shouldSignal = !stopDispatchThread;
pthread_mutex_unlock(&sTDMutex);
}
if(shouldSignal)
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation here. Lines 208-214 use tab characters instead of spaces. This should be indented with spaces to match the project's coding style.

Suggested change
bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
{
shouldSignal = !stopDispatchThread;
pthread_mutex_unlock(&sTDMutex);
}
if(shouldSignal)
bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
{
shouldSignal = !stopDispatchThread;
pthread_mutex_unlock(&sTDMutex);
}
if(shouldSignal)

Copilot uses AI. Check for mistakes.
Comment on lines 556 to 565
FILE *urandom = fopen("/dev/urandom", "r");
if(urandom != NULL && fread(&random_value, sizeof(random_value), 1, urandom) == 1)
{
maxuploadinmilliSec = random_value % (profile->maxUploadLatency - 1);
fclose(urandom);
}
else
{
if(urandom != NULL) fclose(urandom);
maxuploadinmilliSec = (unsigned int)(time(0) % (profile->maxUploadLatency - 1));
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation here. Lines 556, 557, 559, 560, 564, and 565 use tab characters instead of spaces. This should be indented with spaces to match the project's coding style.

Copilot uses AI. Check for mistakes.
while(!stopProcessing)
while(!shouldContinue)
{
pthread_mutex_lock(&tmpRpMutex);
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Logically dead code

Execution cannot reach this statement: "pthread_mutex_lock(&tmpRpMu...".

Medium Impact, CWE-561
DEADCODE

T2Error("Unable to allocate %d bytes of memory for URL at Line %d on %s \n", modified_url_len, __LINE__, __FILE__);
free(httpUrl);
free(url_params);
return NULL;
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Resource leak

Variable "curl" going out of scope leaks the storage it points to.

High Impact, CWE-404
RESOURCE_LEAK

if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

@rdkcmf-jenkins
Copy link
Contributor

rdkcmf-jenkins commented Jan 14, 2026

Coverity Issue - Waiting while holding a lock

Call to "sendCachedReportsOverRBUSMethod" might sleep while holding lock "profile->reuseThreadMutex".

Medium Impact, CWE-667
SLEEP

Issue location

This issue was discovered outside the diff for this Pull Request. You can find it at:
source/bulkdata/profile.c:792

if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

Copilot AI review requested due to automatic review settings January 14, 2026 06:41
if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

T2Info("TIMEOUT for maxUploadLatency of profile %s\n", profile->name);
ret = sendReportsOverRBUSMethod(profile->t2RBUSDest->rbusMethodName, profile->t2RBUSDest->rbusMethodParamList, jsonReport);
}
else if(n == 0)
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of tabs for indentation. The code appears to use spaces for indentation elsewhere. This should be consistent with the rest of the codebase.

Suggested change
else if(n == 0)
else if(n == 0)

Copilot uses AI. Check for mistakes.
Comment on lines 109 to 116
while(t2_queue_count(tmpRpQueue) == 0 && shouldContinue)
{
pthread_cond_wait(&tmpRpCond, &tmpRpMutex);
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to process_rp_thread, the condition variable wait loop checks shouldContinue but doesn't re-evaluate it after pthread_cond_wait returns. If stopProcessing is set while waiting, the thread will continue processing instead of exiting. The shouldContinue variable should be re-checked after pthread_cond_wait returns.

Copilot uses AI. Check for mistakes.
Comment on lines 1331 to 1334
{
n = pthread_cond_timedwait(&xcCond, &xcMutex, &_ts);
}
while(n == EINTR);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of tabs and spaces for indentation. The code appears to use spaces for indentation elsewhere, but tabs are used here. This should be consistent with the rest of the codebase.

Suggested change
{
n = pthread_cond_timedwait(&xcCond, &xcMutex, &_ts);
}
while(n == EINTR);
{
n = pthread_cond_timedwait(&xcCond, &xcMutex, &_ts);
}
while(n == EINTR);

Copilot uses AI. Check for mistakes.
Comment on lines 1276 to 1283
if(temp_url == NULL)
{
T2Error("Unable to allocate %d bytes of memory for URL at Line %d on %s \n", modified_url_len, __LINE__, __FILE__);
free(httpUrl);
free(url_params);
return NULL;
}
httpUrl = temp_url;
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of tabs for indentation. The code appears to use spaces for indentation elsewhere. This should be consistent with the rest of the codebase.

Copilot uses AI. Check for mistakes.
Comment on lines 531 to 537
T2Error("%s pthread_mutex_lock for sTDMutex failed\n", __FUNCTION__);
return;
}
if(!stopDispatchThread)
{
if(pthread_mutex_lock(&sTDMutex) != 0) // mutex lock failed so return from T2ER_Uninit
{
T2Error("%s pthread_mutex_lock for sTDMutex failed\n", __FUNCTION__);
return;
}
stopDispatchThread = true;
threadToJoin = erThread; // Save thread handle while holding lock
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of tabs for indentation. The code appears to use spaces for indentation elsewhere. This should be consistent with the rest of the codebase.

Copilot uses AI. Check for mistakes.
Comment on lines 672 to 677

// Unlock scMutex before sleeping to avoid holding lock during sleep
if(pthread_mutex_unlock(&scMutex) != 0)
{
T2Error("scMutex unlock failed\n");
return T2ERROR_FAILURE;
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of tabs for indentation. The code appears to use spaces for indentation elsewhere. This should be consistent with the rest of the codebase.

Copilot uses AI. Check for mistakes.
Comment on lines 556 to 566
FILE *urandom = fopen("/dev/urandom", "r");
if(urandom != NULL && fread(&random_value, sizeof(random_value), 1, urandom) == 1)
{
maxuploadinmilliSec = random_value % (profile->maxUploadLatency - 1);
fclose(urandom);
}
else
{
if(urandom != NULL) fclose(urandom);
maxuploadinmilliSec = (unsigned int)(time(0) % (profile->maxUploadLatency - 1));
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential division by zero error if profile->maxUploadLatency is 1. The expression (profile->maxUploadLatency - 1) would be 0, causing a modulo by zero which results in undefined behavior. Similar issue exists at line 565. Add a check to ensure maxUploadLatency is greater than 1 before performing the modulo operation.

Suggested change
FILE *urandom = fopen("/dev/urandom", "r");
if(urandom != NULL && fread(&random_value, sizeof(random_value), 1, urandom) == 1)
{
maxuploadinmilliSec = random_value % (profile->maxUploadLatency - 1);
fclose(urandom);
}
else
{
if(urandom != NULL) fclose(urandom);
maxuploadinmilliSec = (unsigned int)(time(0) % (profile->maxUploadLatency - 1));
}
if (profile->maxUploadLatency > 1)
{
FILE *urandom = fopen("/dev/urandom", "r");
if(urandom != NULL && fread(&random_value, sizeof(random_value), 1, urandom) == 1)
{
maxuploadinmilliSec = random_value % (profile->maxUploadLatency - 1);
fclose(urandom);
}
else
{
if(urandom != NULL) fclose(urandom);
maxuploadinmilliSec = (unsigned int)(time(0) % (profile->maxUploadLatency - 1));
}
}
else
{
/* For maxUploadLatency == 1, avoid modulo by zero and use no additional delay */
maxuploadinmilliSec = 0;
}

Copilot uses AI. Check for mistakes.
Comment on lines 254 to 295
while(t2_queue_count(eQueue) == 0 && shouldContinue)
{
T2Debug("Event Queue size is 0, Waiting events from T2ER_Push\n");
int ret = pthread_cond_wait(&erCond, &erMutex);
if(ret != 0) // pthread cond wait failed return after unlock
{
T2Error("%s pthread_cond_wait failed with error code: %d\n", __FUNCTION__, ret);
}
T2Debug("Received signal from T2ER_Push\n");
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition variable wait loop checks shouldContinue but doesn't re-evaluate it after pthread_cond_wait returns. If stopDispatchThread is set while waiting on the condition, the thread will continue processing the event instead of exiting. The shouldContinue variable should be re-checked after pthread_cond_wait returns at line 257.

Copilot uses AI. Check for mistakes.
if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

Copilot AI review requested due to automatic review settings January 14, 2026 07:29
if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

@madhubabutt madhubabutt force-pushed the feature/RDK-60291 branch 2 times, most recently from 28c66a1 to ac77f39 Compare January 14, 2026 07:59
if(!stopDispatchThread)

bool shouldSignal = false;
if(pthread_mutex_lock(&sTDMutex) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Thread deadlock

Calling "pthread_mutex_lock" acquires lock "sTDMutex" while holding lock "erMutex" (count: 1 / 2).

Medium Impact, CWE-833
ORDER_REVERSAL

T2Debug(" profile->triggerReportOnCondition is not set \n");
}
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

T2Debug(" profile->triggerReportOnCondition is not set \n");
}
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

pthread_mutex_unlock(&profile->reuseThreadMutex);
T2Info("%s --out Exiting collect and report Thread\n", __FUNCTION__);
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

Copilot AI review requested due to automatic review settings January 24, 2026 14:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +684 to +697
while (profile->enable && n != ETIMEDOUT)
{
n = pthread_cond_timedwait(&profile->reportcond, &profile->reportMutex, &timeout);
}
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue in the RBUS_METHOD maxUploadLatency path: the while(profile->enable && n != ETIMEDOUT) loop won't break on n==0, so a signal won't cause an early exit as the subsequent logging suggests. Use a single timedwait (retry only on EINTR) or introduce a predicate and break appropriately.

Suggested change
while (profile->enable && n != ETIMEDOUT)
{
n = pthread_cond_timedwait(&profile->reportcond, &profile->reportMutex, &timeout);
}
int waitResult;
do
{
waitResult = pthread_cond_timedwait(&profile->reportcond, &profile->reportMutex, &timeout);
} while (waitResult == EINTR);
n = waitResult;

Copilot uses AI. Check for mistakes.
Comment on lines +908 to +911
if (write(sharedPipeFdStatus[1], &ret, sizeof(T2ERROR)) != sizeof(T2ERROR))
{
T2Error("Failed to write status to pipe\n");
}
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The status pipe write() result is checked, but a short/failed write is only logged and the child still exits normally. This can cause the parent to read an uninitialized/partial T2ERROR value. Consider treating a short/failed write as fatal (set a fallback failure code and exit), and have the parent verify it read exactly sizeof(T2ERROR).

Copilot uses AI. Check for mistakes.
Comment on lines 473 to 476
if (filestat.st_size < 0 || (size_t)filestat.st_size >= sizeof(data))
{
T2Error("File size %ld exceeds buffer capacity %zu for file : %s\n", filestat.st_size, sizeof(data) - 1, filePath);
fclose(fp);
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filestat.st_size is off_t, but the new error message prints it with %ld. On some platforms off_t is not long (e.g., long long), which can cause incorrect logs/UB. Use a portable format (e.g., cast to intmax_t and print with %jd) or cast to long long and use %lld consistently.

Copilot uses AI. Check for mistakes.
T2Debug(" profile->triggerReportOnCondition is not set \n");
}
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

T2Debug(" profile->triggerReportOnCondition is not set \n");
}
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

{
T2Error("Failed to initialize JSON Report\n");
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

{
T2Error("Failed to initialize JSON Report\n");
pthread_mutex_lock(&profile->reportInProgressMutex);
profile->reportInProgress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverity Issue - Data race condition

Accessing "profile->reportInProgress" without holding lock "_Profile.reuseThreadMutex". Elsewhere, "_Profile.reportInProgress" is written to with "_Profile.reuseThreadMutex" held 11 out of 11 times.

Medium Impact, CWE-366
MISSING_LOCK

Copilot AI review requested due to automatic review settings January 24, 2026 15:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

source/bulkdata/profile.c:645

  • In this error path, reportcond is destroyed but reportMutex (initialized earlier when maxUploadLatency > 0) is not destroyed before jumping to reportThreadEnd. This can leak resources and make subsequent pthread_mutex_init on reportMutex undefined. Ensure reportMutex is destroyed on this error path as well.
                                T2Error("Profile : %s pthread_cond_timedwait ERROR!!!\n", profile->name);
                                pthread_mutex_unlock(&profile->reportMutex);
                                pthread_cond_destroy(&profile->reportcond);
                                if(httpUrl)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 626 to +712
T2Error("Profile : %s pthread_cond_timedwait ERROR!!!\n", profile->name);
pthread_mutex_unlock(&profile->reportMutex);
pthread_cond_destroy(&profile->reportcond);
pthread_mutex_lock(&profile->reuseThreadMutex);
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this RBUS_METHOD timedwait error path, reportcond is destroyed but reportMutex (initialized earlier when maxUploadLatency > 0) is not destroyed before jumping to reportThreadEnd. This can leak resources and make subsequent pthread_mutex_init on reportMutex undefined. Ensure reportMutex is destroyed on this error path (and consistently on all paths that destroy reportcond).

Copilot uses AI. Check for mistakes.
Comment on lines +908 to +910
if (write(sharedPipeFdStatus[1], &ret, sizeof(T2ERROR)) != sizeof(T2ERROR))
{
T2Error("Failed to write status to pipe\n");
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If writing the status to the pipe fails (short write or -1), the parent may read an uninitialized/partial status and take the wrong code path. Consider making pipe write failure fatal (e.g., log, set an error status, and exit) rather than continuing with an unreliable IPC result.

Suggested change
if (write(sharedPipeFdStatus[1], &ret, sizeof(T2ERROR)) != sizeof(T2ERROR))
{
T2Error("Failed to write status to pipe\n");
{
size_t totalWritten = 0;
unsigned char *buf = (unsigned char *)&ret;
while (totalWritten < sizeof(T2ERROR))
{
ssize_t bytes = write(sharedPipeFdStatus[1], buf + totalWritten, sizeof(T2ERROR) - totalWritten);
if (bytes < 0)
{
T2Error("Failed to write status to pipe: write error\n");
close(sharedPipeFdStatus[1]);
exit(EXIT_FAILURE);
}
if (bytes == 0)
{
T2Error("Failed to write status to pipe: wrote 0 bytes\n");
close(sharedPipeFdStatus[1]);
exit(EXIT_FAILURE);
}
totalWritten += (size_t)bytes;
}

Copilot uses AI. Check for mistakes.
Comment on lines +1452 to +1456
do
{
n = pthread_cond_timedwait(&xcCond, &xcMutex, &_ts);
}
while(n == EINTR);
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same pattern here: xcThreadMutex is held while doing pthread_cond_timedwait on xcCond with xcMutex. This can prevent stop/uninit from acquiring xcThreadMutex to signal the condition, causing long delays/hangs. Consider not holding xcThreadMutex across the timed wait (use a single mutex for the stop flag + condition, or unlock/relock around the wait).

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 30, 2026 10:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

source/bulkdata/profile.c:1293

  • deleteAllProfiles() writes tempProfile->threadExists = false without holding reuseThreadMutex (or any other lock consistently protecting threadExists). Since CollectAndReport() updates/destroys reuseThreadMutex based on threadExists, this unsynchronized write can race with the worker thread and lead to signaling/joining the wrong state. Update threadExists under reuseThreadMutex (or make it atomic) consistently.
        if (tempProfile->threadExists)
        {
            pthread_mutex_lock(&tempProfile->reuseThreadMutex);
            tempProfile->restartRequested = true;
            pthread_cond_signal(&tempProfile->reuseThread);
            pthread_mutex_unlock(&tempProfile->reuseThreadMutex);
            pthread_join(tempProfile->reportThread, NULL);
            tempProfile->threadExists = false;
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +577 to +579
pthread_mutex_init(&profile->reportMutex, NULL);
pthread_cond_init(&profile->reportcond, NULL);
unsigned int random_value = 0;
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CollectAndReport() initializes profile->reportMutex/profile->reportcond when maxUploadLatency > 0, but teardown is not symmetric across all branches (e.g., the HTTP path destroys both, while the RBUS_METHOD maxUploadLatency path later only destroys the cond var). This can leak pthread resources across repeated reports. Ensure reportMutex is destroyed on every path that initializes it (success, error, and both protocol branches).

Copilot uses AI. Check for mistakes.
Comment on lines 1270 to 1271
params_len += snprintf(url_params + params_len, new_params_len - params_len, "%s=%s&", httpParam->HttpName, httpParamVal);

Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepareHttpUrl() calls snprintf with httpParamVal using a "%s" format, but httpParamVal can be NULL if curl_easy_escape fails (OOM) or returns NULL. Passing NULL to "%s" is undefined behavior and can crash. Add an explicit check for httpParamVal == NULL and skip/abort building that parameter before calling snprintf.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 30, 2026 14:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

T2Error("Failed to create /tmp/.t2ReadyToReceiveEvents flag file \n");
}
setT2EventReceiveState(T2_STATE_COMPONENT_READY);
T2Info("T2 is now Ready to Recieve Events\n");
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in log message: "Recieve" -> "Receive".

Suggested change
T2Info("T2 is now Ready to Recieve Events\n");
T2Info("T2 is now Ready to Receive Events\n");

Copilot uses AI. Check for mistakes.
Comment on lines 100 to +104
pthread_mutex_lock(&tmpRpMutex);
pthread_mutex_lock(&rpMutex);
shouldContinue = !stopProcessing;
pthread_mutex_unlock(&rpMutex);
if(!shouldContinue)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tmpRpQueue operations are protected by tmpRpMutex in this thread, but producers push to tmpRpQueue under rpMutex (see datamodel_processProfile using pthread_mutex_lock(&rpMutex) before t2_queue_push(tmpRpQueue, ...)). This means tmpRpQueue is accessed under different mutexes, which is a data race and can corrupt the queue. Use a single mutex consistently for tmpRpQueue (and pair tmpRpCond with that same mutex), or remove the extra mutex.

Copilot uses AI. Check for mistakes.
Comment on lines 109 to +113
T2Info("%s: Waiting for event from tr-181 \n", __FUNCTION__);
pthread_cond_wait(&tmpRpCond, &tmpRpMutex);
while(t2_queue_count(tmpRpQueue) == 0 && shouldContinue)
{
pthread_cond_wait(&tmpRpCond, &tmpRpMutex);
pthread_mutex_lock(&rpMutex);
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thread waits on tmpRpCond, but datamodel_unInit() never signals tmpRpCond when setting stopProcessing = true. If tmpRpQueue is empty, pthread_join(tmpRpThread, ...) can hang indefinitely. Ensure datamodel_unInit() signals/broadcasts tmpRpCond during shutdown so this wait can be released and the thread can exit.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants