Fix pinned memory leaks if queries are not disposed. #375
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
SC-39730
To pass query buffers to the Core, the C# API has to pin them to keep them alive and prevent the GC from moving them, and they get unpinned when the query gets
Dispose
d. However, if the user forgets to dispose the query, the buffers do not get unpinned, resulting in a memory leak. The nativetiledb_query_t*
still gets freed because it is managed by aSafeHandle
which has a finalizer.This PR fixes this leak by moving the query buffer management logic from
Query
toQueryHandle
. This means that if theQuery
does not get disposed, itsQueryHandle
will also not get disposed, its finalizer will run and both free thetiledb_query_t*
and unpin the buffers.I added a test that verifies that the GC frees the buffers of an undisposed query.
I have considered alternative ways to fix this, like putting finalizers on the
Query
orBufferHandle
classes, but we can't do it because finalizers execute in a non-deterministic order and we must free thetiledb_query_t*
first before unpinning the buffers (and adding a finalizer toBufferHandle
will have performance implications since we are creating more than one finalizable object per query).