Skip to content

fix(local): reclaim leaked update hook context on connection disconnect (#2295) - #2309

Open
djjrip wants to merge 2 commits into
tursodatabase:mainfrom
djjrip:fix/update-hook-leak
Open

djjrip wants to merge 2 commits into
tursodatabase:mainfrom
djjrip:fix/update-hook-leak

Conversation

@djjrip

@djjrip djjrip commented Nov 5, 2026

Copy link
Copy Markdown

Problem

As reported in #2295, registering an update hook through Connection::add_update_hook leaks the final callback allocation (Box<Container>) and all values captured by its closure when the local connection closes.

SQLite's sqlite3_update_hook C API has no built-in destructor callback. In libsql, add_update_hook boxes the closure into a Container and passes a leaked pointer via Box::leak. While subsequent calls to add_update_hook correctly reclaim the previous context, Connection::disconnect was previously invoking sqlite3_close_v2 without first unsetting the hook, permanently leaking the final context allocation and any captured Arc pointers, channels, or resources.

Solution

  1. In Connection::disconnect, deregister the hook prior to calling sqlite3_close_v2 by calling ffi::sqlite3_update_hook(self.raw, None, std::ptr::null_mut()). If a context pointer was returned, reclaim and deallocate it via Box::from_raw(old_data as *mut Container).
  2. Add an integration test (update_hook_closure_dropped_on_disconnect) verifying that closure captures (Arc) are deallocated when the connection is dropped.
  3. Gate the pprof dev-dependency to non-windows targets ([target.'cfg(not(windows))'.dev-dependencies]) in libsql/Cargo.toml so test suites compile cleanly across platforms.

Fixes #2295.

…ct (tursodatabase#2295)

SQLite's sqlite3_update_hook retains a pointer to the callback context without taking a deallocation callback. In libsql, add_update_hook boxes the closure in a Container and leaks it to FFI. When disconnect was called, sqlite3_close_v2 was invoked without deregistering the hook, permanently leaking any captured Arcs and closure state.

This commit deregisters the hook in Connection::disconnect before closing, reclaiming the Container via Box::from_raw. Also adds an integration test verifying captures are deallocated on connection drop, and gates pprof to non-windows targets in dev-dependencies.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rust: final update-hook closure and captures leak on connection close

1 participant