-
Notifications
You must be signed in to change notification settings - Fork 18
Topic/delia 69767 #225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Topic/delia 69767 #225
Conversation
Reason for change: Somehow the execve calling cat in the popen() function is closing a file descriptor used by another thread Test Procedure: Standard NSM chamber testing Risks: Low Priority: P1 Signed-off-by: Jason Thomson <jason_thomson@comcast.com>
|
|
||
| fs = fopen(T2_CACHE_FILE, "r"); | ||
| if (fs != NULL) { | ||
| while ((ch = fgetc(fs)) != EOF) { |
There was a problem hiding this comment.
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 - Truncated stdio return value
Assigning the return value of "fgetc" to char "ch" truncates its value.
Medium Impact, CWE-197
CHAR_IO
There was a problem hiding this 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 PR addresses a critical file descriptor management issue (LLAMA-17349) where popen() was inadvertently closing file descriptors used by other threads in controlMgr. The fix replaces the shell-based line counting (cat | wc -l) with native C file operations, and improves timestamp precision in debug logging.
Key Changes:
- Replaced popen-based line counting with fgetc-based implementation to avoid fd interference
- Enhanced EVENT_DEBUG logging with millisecond-precision timestamps using clock_gettime
- Switched from localtime to thread-safe localtime_r for time conversion
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fs = fopen(T2_CACHE_FILE, "r"); | ||
| if (fs != NULL) { | ||
| while ((ch = fgetc(fs)) != EOF) { | ||
| if (ch == '\n') { | ||
| count++; | ||
| } | ||
| } | ||
|
|
||
| //If the file is not empty and does not contain a newline, call it one line | ||
| if (count == 0 && ftell(fs) > 0) { | ||
| count++; | ||
| } | ||
| fclose(fs); | ||
| fs = NULL; | ||
| } |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The static global variable count (declared at line 58) is never reset before counting lines, causing it to accumulate across multiple invocations of this function. Since cacheEventToFile is called as a thread function (line 730), each new thread will continue incrementing from the previous total, eventually causing all caching to be incorrectly disabled when count exceeds MAX_EVENT_CACHE (200). The count should be reset to 0 at the start of this line counting block or made a local variable.
| FILE *fs = NULL; | ||
| char path[100]; | ||
| pthread_detach(pthread_self()); | ||
| int ch; |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of pthread_detach(pthread_self()) may cause resource leaks. When threads are created via pthread_create at line 730 without the detached attribute, they need to either be joined or explicitly detached to release their resources when they terminate. Since this function is meant to run asynchronously and the calling code doesn't join the thread, the thread should either be created with PTHREAD_CREATE_DETACHED attribute or call pthread_detach(pthread_self()) as was done previously.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please retain the thread attribute to detached.
| while ((ch = fgetc(fs)) != EOF) { | ||
| if (ch == '\n') { | ||
| count++; | ||
| } | ||
| } | ||
|
|
||
| //If the file is not empty and does not contain a newline, call it one line | ||
| if (count == 0 && ftell(fs) > 0) { |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading through the file with fgetc until EOF, ftell may not accurately reflect whether the file had content, especially if fgetc consumed all characters. The file position after EOF doesn't reliably indicate the original file size. Consider using fseek to get the file size before reading, or check if any characters were read during the loop instead of relying on ftell after EOF.
| while ((ch = fgetc(fs)) != EOF) { | |
| if (ch == '\n') { | |
| count++; | |
| } | |
| } | |
| //If the file is not empty and does not contain a newline, call it one line | |
| if (count == 0 && ftell(fs) > 0) { | |
| long file_size = 0; | |
| /* Determine file size before reading, then rewind to start */ | |
| if (fseek(fs, 0, SEEK_END) == 0) { | |
| long pos = ftell(fs); | |
| if (pos > 0) { | |
| file_size = pos; | |
| } | |
| rewind(fs); | |
| } | |
| while ((ch = fgetc(fs)) != EOF) { | |
| if (ch == '\n') { | |
| count++; | |
| } | |
| } | |
| /* If the file is not empty and does not contain a newline, call it one line */ | |
| if (count == 0 && file_size > 0) { |
| strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %H:%M:%S", &timeinfo); | ||
| snprintf(timeBuffer + strlen(timeBuffer), sizeof(timeBuffer) - strlen(timeBuffer), ".%03ld", msecs); |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The snprintf call builds on top of the existing string in timeBuffer by using strlen(timeBuffer) as the offset. While this works, it's more fragile than necessary. Consider using a single snprintf call with a combined format string, or at minimum verify the return value from strftime to ensure it succeeded before appending.
| strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %H:%M:%S", &timeinfo); | |
| snprintf(timeBuffer + strlen(timeBuffer), sizeof(timeBuffer) - strlen(timeBuffer), ".%03ld", msecs); | |
| size_t len = strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %H:%M:%S", &timeinfo); | |
| if (len > 0 && len < sizeof(timeBuffer)) { | |
| int ret = snprintf(timeBuffer + len, sizeof(timeBuffer) - len, ".%03ld", msecs); | |
| if (ret < 0) { | |
| timeBuffer[len] = '\0'; | |
| } | |
| } else { | |
| timeBuffer[0] = '\0'; | |
| } |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please apply the formatting as well that got flagged in L2 workflows. Astyle code formatting commands would be -
find . -name '*.c' -o -name '*.h' | xargs astyle --options=.astylerc
find . -name '*.orig' -type f -delete
Rest of the changes looks good.
| FILE *fs = NULL; | ||
| char path[100]; | ||
| pthread_detach(pthread_self()); | ||
| int ch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please retain the thread attribute to detached.
I have been working on a ticket LLAMA-17349 for a while, trying to figure out how a file descriptor used by one thread in controlMgr is being closed by another controlMgr thread.
Finally I found that the call to cat in cacheEventToFile line "fs = popen ("cat /tmp/t2_caching_file | wc -l", "r");" was closing my thread's fd.
Why this happens I can't really explain, but I have proven that replacing the popen() call with standard C to count line numbers makes the problem not happen anymore.