mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-27 06:53:11 +08:00
Free the thread-local node-type cache to satisfy LeakSanitizer
cbm_kind_in_set builds a thread-local cache of calloc'd symbol bitsets (ks_cache) that was never freed, so LeakSanitizer (Linux x64) reported the per-worker-thread caches as leaks once the previously-empty grammars gained real node-type sets. Add cbm_kind_in_set_free_cache() and call it at worker-thread teardown (extract_worker, beside cbm_slab_destroy_thread) and main-thread exit (test runner, beside sqlite3_shutdown).
This commit is contained in:
@@ -399,6 +399,21 @@ bool cbm_kind_in_set(TSNode node, const char **types) {
|
||||
return kind_in_set_strcmp(node, (const char *const *)types);
|
||||
}
|
||||
|
||||
/* Free the calling thread's node-type bitset cache (the calloc'd `bits` arrays
|
||||
* that cbm_kind_in_set builds lazily). The cache is thread-local, so each worker
|
||||
* thread and the main thread must call this at teardown (worker exit / process
|
||||
* exit) for LeakSanitizer to report no leak. Safe if no cache was ever built. */
|
||||
void cbm_kind_in_set_free_cache(void) {
|
||||
for (int i = 0; i < KS_SLOTS; i++) {
|
||||
free(ks_cache[i].bits);
|
||||
ks_cache[i].bits = NULL;
|
||||
ks_cache[i].lang = NULL;
|
||||
ks_cache[i].types = NULL;
|
||||
ks_cache[i].nsyms = 0;
|
||||
ks_cache[i].exact = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool cbm_has_ancestor_kind(TSNode node, const char *kind, int max_depth) {
|
||||
TSNode cur = node;
|
||||
for (int i = 0; i < max_depth; i++) {
|
||||
|
||||
@@ -42,6 +42,10 @@ TSNode cbm_find_child_by_kind(TSNode parent, const char *kind);
|
||||
// Check if node kind matches a set of types (NULL-terminated array of strings).
|
||||
bool cbm_kind_in_set(TSNode node, const char **types);
|
||||
|
||||
// Free the calling thread's cbm_kind_in_set bitset cache (call at thread/process
|
||||
// teardown so the thread-local cache is not reported as a leak).
|
||||
void cbm_kind_in_set_free_cache(void);
|
||||
|
||||
// Check if node has an ancestor of the given kind, within max_depth levels.
|
||||
bool cbm_has_ancestor_kind(TSNode node, const char *kind, int max_depth);
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ enum { PP_CSHARP_M_PREFIX_LEN = 2 };
|
||||
#include "pipeline/pipeline_internal.h"
|
||||
#include "pipeline/pass_lsp_cross.h" /* cbm_pxc_* helpers for fused cross-file LSP */
|
||||
#include "pipeline/lsp_resolve.h"
|
||||
#include "helpers.h" /* cbm_kind_in_set_free_cache — per-worker-thread cache teardown */
|
||||
#include "pipeline/worker_pool.h"
|
||||
#include "foundation/compat.h"
|
||||
#include "foundation/compat_thread.h"
|
||||
@@ -635,6 +636,7 @@ static void extract_worker(int worker_id, void *ctx_ptr) {
|
||||
|
||||
/* Final cleanup (parser already destroyed in loop, just slab state) */
|
||||
cbm_slab_destroy_thread();
|
||||
cbm_kind_in_set_free_cache(); /* free this worker thread's node-type bitset cache */
|
||||
}
|
||||
|
||||
static void merge_pkg_entries(cbm_pipeline_ctx_t *ctx, cbm_pkg_entries_t *pkg_entries,
|
||||
|
||||
+7
-1
@@ -80,6 +80,11 @@ extern void suite_incremental(void);
|
||||
extern void suite_simhash(void);
|
||||
extern void suite_stack_overflow(void);
|
||||
|
||||
/* Free the main thread's thread-local node-type bitset cache before exit so
|
||||
* LeakSanitizer (Linux x64) doesn't report it. Worker threads free their own
|
||||
* caches at thread teardown (pass_parallel.c). */
|
||||
extern void cbm_kind_in_set_free_cache(void);
|
||||
|
||||
int main(void) {
|
||||
printf("\n codebase-memory-mcp C test suite\n");
|
||||
|
||||
@@ -207,7 +212,8 @@ int main(void) {
|
||||
|
||||
RUN_SUITE(incremental);
|
||||
|
||||
/* Release sqlite3 internal caches so ASan doesn't report them as leaks */
|
||||
/* Release process-lifetime caches so LeakSanitizer reports no leaks. */
|
||||
cbm_kind_in_set_free_cache();
|
||||
sqlite3_shutdown();
|
||||
TEST_SUMMARY();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user