]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-144377: Clean up sqlite3 Connection's list of weakrefs to Cursor objects (#144378)
authorThomas Kluyver <thomas@kluyver.me.uk>
Tue, 3 Feb 2026 12:36:12 +0000 (12:36 +0000)
committerGitHub <noreply@github.com>
Tue, 3 Feb 2026 12:36:12 +0000 (13:36 +0100)
Modules/_sqlite/connection.c
Modules/_sqlite/connection.h
Modules/_sqlite/cursor.c

index cde06c965ad4e34871c811d6cd282cab20acbc74..af63271b9fd9717ccad28bc43aed64452d403bca 100644 (file)
@@ -38,7 +38,6 @@
 #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
 #include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
 #include "pycore_unicodeobject.h" // _PyUnicode_AsUTF8NoNUL
-#include "pycore_weakref.h"
 
 #include <stdbool.h>
 
@@ -144,7 +143,6 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
 [clinic start generated code]*/
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
 
-static int _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
 static void incref_callback_context(callback_context *ctx);
 static void decref_callback_context(callback_context *ctx);
 static void set_callback_context(callback_context **ctx_pp,
@@ -285,17 +283,10 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
         goto error;
     }
 
-    /* Create lists of weak references to cursors and blobs */
-    PyObject *cursors = PyList_New(0);
-    if (cursors == NULL) {
-        Py_DECREF(statement_cache);
-        goto error;
-    }
-
+    /* Create lists of weak references to blobs */
     PyObject *blobs = PyList_New(0);
     if (blobs == NULL) {
         Py_DECREF(statement_cache);
-        Py_DECREF(cursors);
         goto error;
     }
 
@@ -308,9 +299,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
     self->check_same_thread = check_same_thread;
     self->thread_ident = PyThread_get_thread_ident();
     self->statement_cache = statement_cache;
-    self->cursors = cursors;
     self->blobs = blobs;
-    self->created_cursors = 0;
     self->row_factory = Py_NewRef(Py_None);
     self->text_factory = Py_NewRef(&PyUnicode_Type);
     self->trace_ctx = NULL;
@@ -392,7 +381,6 @@ connection_traverse(PyObject *op, visitproc visit, void *arg)
     pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
     Py_VISIT(Py_TYPE(self));
     Py_VISIT(self->statement_cache);
-    Py_VISIT(self->cursors);
     Py_VISIT(self->blobs);
     Py_VISIT(self->row_factory);
     Py_VISIT(self->text_factory);
@@ -417,7 +405,6 @@ connection_clear(PyObject *op)
 {
     pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
     Py_CLEAR(self->statement_cache);
-    Py_CLEAR(self->cursors);
     Py_CLEAR(self->blobs);
     Py_CLEAR(self->row_factory);
     Py_CLEAR(self->text_factory);
@@ -562,11 +549,6 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
         return NULL;
     }
 
-    if (_pysqlite_drop_unused_cursor_references(self) < 0) {
-        Py_DECREF(cursor);
-        return NULL;
-    }
-
     if (cursor && self->row_factory != Py_None) {
         Py_INCREF(self->row_factory);
         Py_XSETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
@@ -1067,38 +1049,6 @@ error:
     PyGILState_Release(threadstate);
 }
 
-static int
-_pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
-{
-    /* we only need to do this once in a while */
-    if (self->created_cursors++ < 200) {
-        return 0;
-    }
-
-    self->created_cursors = 0;
-
-    PyObject* new_list = PyList_New(0);
-    if (!new_list) {
-        return -1;
-    }
-
-    assert(PyList_CheckExact(self->cursors));
-    Py_ssize_t imax = PyList_GET_SIZE(self->cursors);
-    for (Py_ssize_t i = 0; i < imax; i++) {
-        PyObject* weakref = PyList_GET_ITEM(self->cursors, i);
-        if (_PyWeakref_IsDead(weakref)) {
-            continue;
-        }
-        if (PyList_Append(new_list, weakref) != 0) {
-            Py_DECREF(new_list);
-            return -1;
-        }
-    }
-
-    Py_SETREF(self->cursors, new_list);
-    return 0;
-}
-
 /* Allocate a UDF/callback context structure. In order to ensure that the state
  * pointer always outlives the callback context, we make sure it owns a
  * reference to the module itself. create_callback_context() is always called
index 703396a0c8db53d8eaee8c295c38e64887379a6b..a2241bd540669cf32d7a2ac0385e5fdb3f32f3ad 100644 (file)
@@ -70,14 +70,9 @@ typedef struct
 
     PyObject *statement_cache;
 
-    /* Lists of weak references to cursors and blobs used within this connection */
-    PyObject *cursors;
+    /* Lists of weak references to blobs used within this connection */
     PyObject *blobs;
 
-    /* Counters for how many cursors were created in the connection. May be
-     * reset to 0 at certain intervals */
-    int created_cursors;
-
     PyObject* row_factory;
 
     /* Determines how bytestrings from SQLite are converted to Python objects:
index 4611c9e5e3e43749884422c2bf53d506ac8ba4e3..5a61e43617984d98fca202880a23b3d091b9253d 100644 (file)
@@ -99,28 +99,6 @@ class _sqlite3.Cursor "pysqlite_Cursor *" "clinic_state()->CursorType"
 [clinic start generated code]*/
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c5b8115c5cf30f1]*/
 
-/*
- * Registers a cursor with the connection.
- *
- * 0 => error; 1 => ok
- */
-static int
-register_cursor(pysqlite_Connection *connection, PyObject *cursor)
-{
-    PyObject *weakref = PyWeakref_NewRef((PyObject *)cursor, NULL);
-    if (weakref == NULL) {
-        return 0;
-    }
-
-    if (PyList_Append(connection->cursors, weakref) < 0) {
-        Py_CLEAR(weakref);
-        return 0;
-    }
-
-    Py_DECREF(weakref);
-    return 1;
-}
-
 /*[clinic input]
 _sqlite3.Cursor.__init__ as pysqlite_cursor_init
 
@@ -160,10 +138,6 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
         return -1;
     }
 
-    if (!register_cursor(connection, (PyObject *)self)) {
-        return -1;
-    }
-
     self->initialized = 1;
 
     return 0;