mirror of
https://github.com/python/cpython.git
synced 2026-05-06 04:37:33 -04:00
gh-144377: Clean up sqlite3 Connection's list of weakrefs to Cursor objects (#144378)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user