Repository navigation
fix(store,ui): export paired free functions for FFI callers (#1762) - #1996
Conversation
cbm_store_fetch_call_edges, cbm_leiden/cbm_louvain, and
cbm_layout_to_json document caller-owned memory ("caller frees
both" / "the caller frees it" / "Caller must free()") but exported
no matching free function, unlike the rest of the API
(cbm_store_find_nodes -> cbm_store_free_nodes,
cbm_layout_compute -> cbm_layout_free, etc.). From C a bare free()
works via static linking, but a caller across an FFI boundary (e.g.
C# P/Invoke) has no way to reach the DLL's internal free() unless
it is exported by name.
Adds three paired free functions following the existing pattern:
- cbm_store_free_call_edges(src, tgt)
- cbm_leiden_free(result)
- cbm_layout_free_json(json)
Updates the one internal production caller (mcp.c SCC analysis) to
use cbm_store_free_call_edges instead of a bare free(), and the
existing unit tests for cbm_leiden/cbm_louvain/cbm_layout_to_json
to use the new paired frees. Adds fetch_call_edges_basic,
fetch_call_edges_truncated, and fetch_call_edges_empty_project to
test_store_arch.c, covering cbm_store_fetch_call_edges /
cbm_store_free_call_edges, which had no prior test coverage.
Fixes DeusData#1762
Signed-off-by: Jumaga2015 <jumaga2015@gmail.com>
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
|
Approved on merit. I checked every claim against the tree rather than taking them, and they all hold:
The heap-mismatch paragraph is what makes this a bug rather than a nicety, and I want to quote it back because it is the part a reviewer might otherwise skim:
That is exactly right, and it is why "the caller can just free it" is true from C and false across an FFI boundary. The failure it produces is the worst kind — silent, delayed, and attributed to unrelated code. So today a P/Invoke caller's only safe options are to leak on every call or to skip Noting that all three payloads are flat — Updating the internal On the unanswered question
You asked, we did not answer, and you chose by following existing convention rather than guessing. That is the best possible way to handle our silence, and the answer you arrived at is the one I would have given: three specific frees. A generic Sorry you had to proceed without a reply. That is the third PR today where a contributor asked a design question on an issue and got silence, which is a queue problem on our side, not yours. Before mergeThis adds three exported symbols, so it is a public-surface addition — additive, conventional, and reversible only in the sense that removing an export is a break, which is worth being deliberate about. I am satisfied it earns them. CI is heavily backlogged on this repo right now (44 runs queued against 3 executing), so I am deliberately not forcing a re-run. Once it reports green I will merge. Thank you — this is a careful, well-evidenced fix. |
|
Your CI came back 31 green / 4 red. None of the four are yours — I traced them, and it is worth telling you exactly what happened so you do not go looking. The root failure is on the Windows shard, and it is a harness error rather than a test assertion: That string is raised at The other three fall out of it: We already have the fix open. PR #1823 changes precisely that line: - if windows_descendants(process.pid, kill_grace):
+ if windows_descendants(process.pid, windows_helper_timeout(kill_grace)):Its reasoning is exactly your symptom: So: nothing to change on your side. #1823 is blocked on a maintainer step, I am chasing it, and I will re-run this once it lands. My review from earlier stands — approved on merit, merging on green. |
|
Thank you, and I am sorry for the silence: I approved this on merit on 2 September and then left it for twenty days. The review stands — three documented caller-owned allocations with no exported release, named to match the existing convention, and your One thing changed underneath you, and it is ours to resolve, not yours. On 13 September we added a memory-core linter with a per-file ratchet of raw allocator call sites ( Your four |
Brings the branch up to main at a222715. Two conflicts, both resolved by keeping both sides: - src/ui/layout3d.h: the new cbm_layout_free_json declaration sits before main's region-level layout section. - tests/test_store_arch.c: the Leiden/Louvain tests release their results through the new cbm_leiden_free; main's leiden_result_memory_core_ownership test is kept. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The three exported release functions added for DeusData#1762 freed raw heap blocks. Since the memory-core ratchet landed, the allocating side has to go through the core as well, and on current main cbm_leiden already allocates its result in CBM_MEM_CLASS_OTHER, so a raw free() in cbm_leiden_free left the class counters drifting. - cbm_store_fetch_call_edges: allocate and grow the source/target arrays with cbm_alloc/cbm_realloc in CBM_MEM_CLASS_STORE. An allocation failure now finalizes the statement, releases both arrays and returns CBM_STORE_ERR instead of writing through a NULL array. - cbm_store_free_call_edges, cbm_leiden_free and cbm_layout_free_json release with cbm_free in the class the matching allocation used. - cbm_layout_to_json writes its output through cbm_json_writer_allocator, so the string is an OTHER-class core block; the UI server's five release sites now call cbm_layout_free_json. - The header comments name the paired free instead of "caller frees". - Tests: ownership checks for all three pairs measure the class counters across the allocating call and the paired free, so a raw allocation on either side fails; the call-edge check grows past the initial capacity. Refs DeusData#1762 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Thank you, @Jumaga2015, and thank you for waiting while we settled the memory-core question from September 21. As promised there, we resolved it on our side and pushed two commits on top of your branch; your own commit is unchanged. What you got right, and what we kept exactly as you wrote it: the three exported release functions, their names (which follow the existing paired-free convention), their signatures, the switch of the internal SCC caller to cbm_store_free_call_edges, and your call-edge tests, including the truncation case that really exercises the cap. Your check that all three payloads are flat is what keeps a single release call complete. What we changed, and why:
Your public API is exactly as you proposed it: the same three names and signatures, and a caller across an FFI boundary still releases everything through them. We will merge once CI is green. Thank you again for a careful, well-reasoned fix. |
|
Thank you for adding the paired release APIs and ownership tests. I updated this branch with current main in |
|
Thank you again for the paired-release APIs. The October updates record that we completed the memory-core adaptation and refreshed the branch, resolving the earlier allocator-policy question. The remaining follow-up is on us; sorry for the delay, and I’ll follow up soon. |
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Thanks again, @Jumaga2015. Several other pull requests landed on main this evening, including changes in files this one also touches, so we merged current main into your branch once more (one signed-off merge commit, c62fd01; your changes are untouched). That keeps the required checks honest against today's tree; we will merge once they are green. Please pull before pushing again. |
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Thank you for your patience, @Jumaga2015. CI went green on this branch, but this evening's merges on main touched files this pull request also changes, so that green no longer covered today's main. We merged current main into the branch once more (one merge commit, 1246713; your changes are untouched) and will merge once the fresh checks are green. Please pull before pushing again. |
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Thank you for your patience, @Jumaga2015. A pull request that merged into main a few minutes ago (#2600) changes src/mcp/mcp.c, which this pull request also changes, so the CI run in progress here could no longer vouch for today's main. We merged current main into your branch once more (one merge commit, 5842b84; it merged cleanly and your own change is untouched) and started a fresh run. We will merge once the required checks are green. Please pull before pushing again. |
|
Merged as 164b2dc - thank you, @Jumaga2015! The functions that hand caller-owned memory to FFI callers (cbm_store_fetch_call_edges, cbm_leiden, cbm_layout_to_json) now have exported, paired free functions, so bindings can release that memory through the same allocator that produced it. Thank you for reporting #1762, for the fix, and for staying with it through the memory-core migration and all the refreshes. |
Fixes #1762. Export allocator-matched release functions for caller-owned call-edge arrays, Leiden/Louvain results, and layout JSON so FFI callers can release memory through the allocating library. The API pairs are
cbm_store_fetch_call_edges/cbm_store_free_call_edges,cbm_leidenorcbm_louvain/cbm_leiden_free, andcbm_layout_to_json/cbm_layout_free_json.The implementation uses the memory core: STORE-class allocation/reallocation for call edges, OTHER-class allocation and paired release for clustering results, and a core-backed JSON writer with OTHER-class release. Internal MCP/UI callers use the matching release functions. Tests cover call-edge results including truncation and empty results, and update the clustering/layout ownership checks.
The maintainer integration preserves the contributor’s paired-release API and credit while adapting it to the current allocator design. Required hosted CI on the refreshed head is pending; earlier-head test results are not claimed as final validation.