| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
There was a problem hiding this comment.
2 issues found across 4 files
Confidence score: 2/5
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/libnetdata/dictionary/dictionary-unittest.c">
<violation number="1" location="src/libnetdata/dictionary/dictionary-unittest.c:1093">
P2: Handle `nd_thread_create` failures before waiting on the ready flags; otherwise a failed thread creation will hang the test in the ready-wait loop.</violation>
</file>
<file name="src/libnetdata/dictionary/dictionary-traversal.c">
<violation number="1" location="src/libnetdata/dictionary/dictionary-traversal.c:81">
P1: Reentrant mode can leak the traversal lock on the new destroyed-after-lock path, causing deadlocks.</violation>
</file>
sequenceDiagram
participant D as Destroyer Thread
participant RW as Reader/Writer Thread
participant Idx as Dictionary Index (Hashtable)
participant DQ as Deferred Queue
Note over D, DQ: Fixes TOCTOU race in dictionary_destroy()
D->>D: Set DICT_FLAG_DESTROYED
rect rgb(240, 240, 240)
Note right of D: NEW: Synchronized Index Teardown
D->>Idx: NEW: Acquire Index Write Lock
par Concurrent Access
RW->>Idx: Attempt lock (Read or Write)
Note over RW: RW blocks until Destroyer finishes index wipe
and Destruction
D->>Idx: NEW: hashtable_destroy_unsafe()
D->>Idx: NEW: Release Index Write Lock
end
end
RW->>Idx: Acquire Lock (Granted)
RW->>RW: NEW: Re-check is_dictionary_destroyed()
alt is_dictionary_destroyed is true
RW-->>RW: NEW: Release lock and exit safely
else is_dictionary_destroyed is false (unchanged path)
RW->>Idx: Access items
RW-->>RW: Release lock
end
Note over D, DQ: NEW: Final reference check before freeing memory
alt Items still referenced (Refcount > 0)
D->>DQ: NEW: Fallback: Queue for deferred destruction
Note over D, DQ: Cleanup delayed until all acquired items are released
else No references
D->>D: Free all dictionary resources immediately
end
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Sorry, something went wrong.
There was a problem hiding this comment.
This PR hardens the DICTIONARY implementation against a TOCTOU race during dictionary_destroy() in multithreaded use by synchronizing “destroyed” checks under the relevant locks and preventing concurrent index lookups from racing with teardown.
Changes:
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/libnetdata/dictionary/dictionary.c | Updates dictionary_destroy() to set the destroyed flag and tear down the index under lock, with a re-check for referenced items to choose deferred destruction safely. |
| src/libnetdata/dictionary/dictionary-item.h | Adds destroyed re-checks under the index lock for delete/add/find operations to close TOCTOU windows. |
| src/libnetdata/dictionary/dictionary-traversal.c | Adds destroyed re-checks after acquiring traversal locks so traversal can’t proceed on a dictionary that becomes destroyed concurrently. |
| src/libnetdata/dictionary/dictionary-unittest.c | Introduces a forked stress test that runs concurrent get/set/traverse while destroying the dictionary to validate the fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/libnetdata/dictionary/dictionary-unittest.c">
<violation number="1" location="src/libnetdata/dictionary/dictionary-unittest.c:1176">
P1: Timeout detection is broken: a still-running child can be treated as exited because `status` remains 0 when `waitpid(..., WNOHANG)` never reaps it.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Sorry, something went wrong.
There was a problem hiding this comment.
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)src/libnetdata/dictionary/dictionary-item.h:476
dictionary_index_lock_wrlock(dict);
// Re-check under the index lock. This synchronizes with
// dictionary_destroy(), which sets the destroyed flag and then takes
// this lock before tearing down the index.
if(unlikely(is_dictionary_destroyed(dict))) {
dictionary_index_wrlock_unlock(dict);
return NULL;
}
bool added_or_updated = false;
size_t spins = 0;
DICTIONARY_ITEM *item = NULL;
do {
void *handle = hashtable_insert_unsafe(dict, name, name_len);
item = hashtable_insert_handle_to_item_unsafe(dict, handle);
if (likely(item == NULL)) {
// a new item added to the index
// create the dictionary item
item = dict_item_create_with_hooks(dict, name, name_len, value, value_len, constructor_data, master_item);
pointer_add(dict, item);
hashtable_set_item_unsafe(dict, handle, item);
// unlock the index lock, before we add it to the linked list
// DON'T DO IT THE OTHER WAY AROUND - DO NOT CROSS THE LOCKS!
dictionary_index_wrlock_unlock(dict);
item_linked_list_add(dict, item);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)src/libnetdata/dictionary/dictionary.c:717
// Destroy the index while holding the items write lock.
// This prevents a TOCTOU race: without this, a reader could pass the
// is_dictionary_destroyed() check, then acquire an item via the index,
// after we've decided to force-free all items.
// By destroying the index here, any concurrent dictionary_get_and_acquire_item()
// that acquires the index lock after this point will find an empty index.
// This uses hashtable_destroy_unsafe(); the later cleanup path in
// dictionary_free_all_resources() may invoke the same index teardown
// again, so this relies on that full destruction flow being safe to repeat.
dictionary_index_lock_wrlock(dict);
hashtable_destroy_unsafe(dict);
dictionary_index_wrlock_unlock(dict);
// Re-check: a reader that held the index read lock during the destroy
// above may have acquired an item before we got the index write lock.
// If so, fall back to the deferred destruction path.
if(dictionary_referenced_items(dict)) {
dictionary_queue_for_destruction(dict);
ll_recursive_unlock(dict, DICTIONARY_LOCK_WRITE);
return 0;
}
ll_recursive_unlock(dict, DICTIONARY_LOCK_WRITE);
size_t freed;
dictionary_free_all_resources(dict, &freed, true);
return freed;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
- Add synchronized checks to prevent accessing destroyed dictionaries in multithreaded scenarios. - Introduce unit tests to reproduce and validate the fix for concurrent get/set/traverse operations during dictionary destruction. - Update dictionary destruction logic to mark and lock the dictionary index, mitigating race conditions.
- Add a timeout mechanism to prevent indefinite hangs during the test. - Implement child process termination to handle potential test deadlocks.
… and unit tests - Ensure proper unlocking in `dictionary_foreach_done` to handle reentrant mode locks. - Add error handling in unit tests to clean up resources when thread creation fails.
…dling and readability - Replace `timed_out` flag with `reaped` for clarity. - Simplify logic for detecting and handling hung child processes.
- Implement `nd_is_running_under_ci()` in `libnetdata/os/ci.c` for centralized CI environment checking. - Replace the duplicate `is_ci()` logic in `status-file.c` with the new library function. - Update build files and headers to include the new module.
- Add `DICT_FLAG_QUEUED_FOR_DESTRUCTION` to track queued dictionaries. - Refactor `dictionary_queue_for_destruction()` to prevent redundant operations. - Improve `dictionary_destroy()` handling for destroyed or null dictionaries. - Add platform-specific handling for `dictionary_destroy_race_unittest`, skipping unsupported tests on Windows.
- Hold acquired item to ensure delayed destruction path is tested. - Add error handling for `dictionary_get_and_acquire_item` failures. - Ensure proper item release and dictionary cleanup in all cases.
…and CI detection - Fix EINTR handling in `dictionary_destroy()` TOCTOU tests for better reliability. - Add synchronization to `dictionary_queue_for_destruction` to prevent redundant locking. - Refactor CI environment detection to enhance modularity and include missing headers.
…rove synchronization - Remove permanent item acquisition to avoid forcing the old delayed-destroy path. - Rely on transient in-flight accesses to test synchronization during destruction. - Reduce iterations for CI to improve test reliability and runtime.
There was a problem hiding this comment.
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
There was a problem hiding this comment.
No issues happening during runtime. LGTM!
Sorry, something went wrong.
* Fix TOCTOU race in dictionary_destroy() - Add synchronized checks to prevent accessing destroyed dictionaries in multithreaded scenarios. - Introduce unit tests to reproduce and validate the fix for concurrent get/set/traverse operations during dictionary destruction. - Update dictionary destruction logic to mark and lock the dictionary index, mitigating race conditions. * Improve TOCTOU test reliability in dictionary_destroy() - Add a timeout mechanism to prevent indefinite hangs during the test. - Implement child process termination to handle potential test deadlocks. * Fix race condition and improve error handling in dictionary traversal and unit tests - Ensure proper unlocking in `dictionary_foreach_done` to handle reentrant mode locks. - Add error handling in unit tests to clean up resources when thread creation fails. * Refactor TOCTOU test in `dictionary_destroy()` to improve process handling and readability - Replace `timed_out` flag with `reaped` for clarity. - Simplify logic for detecting and handling hung child processes. * Move CI environment detection to `libnetdata` and refactor calls - Implement `nd_is_running_under_ci()` in `libnetdata/os/ci.c` for centralized CI environment checking. - Replace the duplicate `is_ci()` logic in `status-file.c` with the new library function. - Update build files and headers to include the new module. * Fix dictionary destruction logic and enhance platform compatibility - Add `DICT_FLAG_QUEUED_FOR_DESTRUCTION` to track queued dictionaries. - Refactor `dictionary_queue_for_destruction()` to prevent redundant operations. - Improve `dictionary_destroy()` handling for destroyed or null dictionaries. - Add platform-specific handling for `dictionary_destroy_race_unittest`, skipping unsupported tests on Windows. * Clarify comments for safe repeated index teardown during dictionary destruction * Fix dictionary destruction handling in unit tests - Hold acquired item to ensure delayed destruction path is tested. - Add error handling for `dictionary_get_and_acquire_item` failures. - Ensure proper item release and dictionary cleanup in all cases. * Improve error handling and synchronization in dictionary destruction and CI detection - Fix EINTR handling in `dictionary_destroy()` TOCTOU tests for better reliability. - Add synchronization to `dictionary_queue_for_destruction` to prevent redundant locking. - Refactor CI environment detection to enhance modularity and include missing headers. * Use unique keys in dictionary destruction unit test * Refactor `dictionary_destroy_race_unittest` to simplify logic and improve synchronization - Remove permanent item acquisition to avoid forcing the old delayed-destroy path. - Rely on transient in-flight accesses to test synchronization during destruction. - Reduce iterations for CI to improve test reliability and runtime.
* Fix TOCTOU race in dictionary_destroy() - Add synchronized checks to prevent accessing destroyed dictionaries in multithreaded scenarios. - Introduce unit tests to reproduce and validate the fix for concurrent get/set/traverse operations during dictionary destruction. - Update dictionary destruction logic to mark and lock the dictionary index, mitigating race conditions. * Improve TOCTOU test reliability in dictionary_destroy() - Add a timeout mechanism to prevent indefinite hangs during the test. - Implement child process termination to handle potential test deadlocks. * Fix race condition and improve error handling in dictionary traversal and unit tests - Ensure proper unlocking in `dictionary_foreach_done` to handle reentrant mode locks. - Add error handling in unit tests to clean up resources when thread creation fails. * Refactor TOCTOU test in `dictionary_destroy()` to improve process handling and readability - Replace `timed_out` flag with `reaped` for clarity. - Simplify logic for detecting and handling hung child processes. * Move CI environment detection to `libnetdata` and refactor calls - Implement `nd_is_running_under_ci()` in `libnetdata/os/ci.c` for centralized CI environment checking. - Replace the duplicate `is_ci()` logic in `status-file.c` with the new library function. - Update build files and headers to include the new module. * Fix dictionary destruction logic and enhance platform compatibility - Add `DICT_FLAG_QUEUED_FOR_DESTRUCTION` to track queued dictionaries. - Refactor `dictionary_queue_for_destruction()` to prevent redundant operations. - Improve `dictionary_destroy()` handling for destroyed or null dictionaries. - Add platform-specific handling for `dictionary_destroy_race_unittest`, skipping unsupported tests on Windows. * Clarify comments for safe repeated index teardown during dictionary destruction * Fix dictionary destruction handling in unit tests - Hold acquired item to ensure delayed destruction path is tested. - Add error handling for `dictionary_get_and_acquire_item` failures. - Ensure proper item release and dictionary cleanup in all cases. * Improve error handling and synchronization in dictionary destruction and CI detection - Fix EINTR handling in `dictionary_destroy()` TOCTOU tests for better reliability. - Add synchronization to `dictionary_queue_for_destruction` to prevent redundant locking. - Refactor CI environment detection to enhance modularity and include missing headers. * Use unique keys in dictionary destruction unit test * Refactor `dictionary_destroy_race_unittest` to simplify logic and improve synchronization - Remove permanent item acquisition to avoid forcing the old delayed-destroy path. - Rely on transient in-flight accesses to test synchronization during destruction. - Reduce iterations for CI to improve test reliability and runtime. (cherry picked from commit cd741f2)
| Back | FazBrowse Home | New Git URL |
Summary
Summary by cubic
Fixes a TOCTOU race in dictionary_destroy() that let threads access items during free. Adds synchronized destroyed-state checks in lookups/traversal, hardens the stress test to avoid crashes or hangs, and centralizes CI detection.
Bug Fixes
Refactors
Written for commit 6bbda97. Summary will update on new commits.