Skip to content

Conversation

@takluyver
Copy link
Contributor

@takluyver takluyver commented Feb 3, 2026

Using conn.blobopen() puts a weakref to the new blob object into a list, but dead weakrefs are never cleaned up.

This adds a check to go through and clean up dead weakrefs on every 200th blob opened, closely based on the code I removed in #144378 doing the same thing for Cursor weakrefs.

Closes #144424.

_pysqlite_drop_unused_blob_references(pysqlite_Connection* self)
{
/* we only need to do this once in a while */
if (self->created_blobs++ < 200) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we open new blobs without closing them, we will spend quadratic time on making copy of the list. We can avoid this if make the threshold proportional to the size of the list.

Suggested change
if (self->created_blobs++ < 200) {
self->created_blobs++;
if (self->created_blobs < 200 || self->created_blobs < PyList_GET_SIZE(self->blobs) / 4) {

(the coefficient can be different).

for (Py_ssize_t i = 0; i < imax; i++) {
PyObject* weakref = PyList_GET_ITEM(self->blobs, i);
if (_PyWeakref_IsDead(weakref)) {
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sqlite3 Blob objects leave behind weakrefs which are never cleaned up

2 participants