From 6ece632c6bdea264ea23b0669ac12f7ad38b1e47 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 21:55:27 +0100 Subject: [PATCH 01/14] sqlite.Connection type now implements GC protocol --- Modules/_sqlite/connection.c | 52 ++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 28932726b74257..27d58dfc0060fa 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -225,28 +225,51 @@ pysqlite_do_all_statements(pysqlite_Connection *self, int action, } } +static int +connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) +{ + Py_VISIT(self->statement_cache); + Py_VISIT(self->function_pinboard_trace_callback); + Py_VISIT(self->function_pinboard_progress_handler); + Py_VISIT(self->function_pinboard_authorizer_cb); + Py_VISIT(self->row_factory); + Py_VISIT(self->text_factory); + Py_VISIT(self->collations); + Py_VISIT(self->statements); + Py_VISIT(self->cursors); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +connection_clear(pysqlite_Connection *self) +{ + Py_CLEAR(self->statement_cache); + Py_CLEAR(self->isolation_level); + Py_CLEAR(self->function_pinboard_trace_callback); + Py_CLEAR(self->function_pinboard_progress_handler); + Py_CLEAR(self->function_pinboard_authorizer_cb); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->text_factory); + Py_CLEAR(self->collations); + Py_CLEAR(self->statements); + Py_CLEAR(self->cursors); + return 0; +} + static void pysqlite_connection_dealloc(pysqlite_Connection *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_XDECREF(self->statement_cache); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); /* Clean up if user has not called .close() explicitly. */ if (self->db) { sqlite3_close_v2(self->db); + self->db = NULL; } - Py_XDECREF(self->isolation_level); - Py_XDECREF(self->function_pinboard_trace_callback); - Py_XDECREF(self->function_pinboard_progress_handler); - Py_XDECREF(self->function_pinboard_authorizer_cb); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->text_factory); - Py_XDECREF(self->collations); - Py_XDECREF(self->statements); - Py_XDECREF(self->cursors); - tp->tp_free(self); Py_DECREF(tp); } @@ -1914,16 +1937,17 @@ static PyType_Slot connection_slots[] = { {Py_tp_methods, connection_methods}, {Py_tp_members, connection_members}, {Py_tp_getset, connection_getset}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_connection_init}, {Py_tp_call, pysqlite_connection_call}, + {Py_tp_traverse, connection_traverse}, + {Py_tp_clear, connection_clear}, {0, NULL}, }; static PyType_Spec connection_spec = { .name = MODULE_NAME ".Connection", .basicsize = sizeof(pysqlite_Connection), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = connection_slots, }; From 866060958c17a4ab6f677362ac357433dc6fca91 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 21:58:56 +0100 Subject: [PATCH 02/14] sqlite.Cursor type now implements GC protocol --- Modules/_sqlite/cursor.c | 44 +++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index b71f780a0b4dfd..9861460ad80fe7 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -81,27 +81,46 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self, return 0; } -static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) +static int +cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); + Py_VISIT(self->connection); + Py_VISIT(self->row_cast_map); + Py_VISIT(self->row_factory); + Py_VISIT(self->next_row); + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cursor_clear(pysqlite_Cursor *self) +{ /* Reset the statement if the user has not closed the cursor */ if (self->statement) { pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); + Py_CLEAR(self->statement); } - Py_XDECREF(self->connection); - Py_XDECREF(self->row_cast_map); - Py_XDECREF(self->description); - Py_XDECREF(self->lastrowid); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->next_row); + Py_CLEAR(self->connection); + Py_CLEAR(self->row_cast_map); + Py_CLEAR(self->description); + Py_CLEAR(self->lastrowid); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->next_row); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} + +static void +cursor_dealloc(pysqlite_Cursor *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -1006,21 +1025,22 @@ static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); static PyType_Slot cursor_slots[] = { - {Py_tp_dealloc, pysqlite_cursor_dealloc}, + {Py_tp_dealloc, cursor_dealloc}, {Py_tp_doc, (void *)cursor_doc}, {Py_tp_iter, PyObject_SelfIter}, {Py_tp_iternext, pysqlite_cursor_iternext}, {Py_tp_methods, cursor_methods}, {Py_tp_members, cursor_members}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cursor_init}, + {Py_tp_traverse, cursor_traverse}, + {Py_tp_clear, cursor_clear}, {0, NULL}, }; static PyType_Spec cursor_spec = { .name = MODULE_NAME ".Cursor", .basicsize = sizeof(pysqlite_Cursor), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cursor_slots, }; From 13bc519a06221896f7c2bf0718743a4f1d61bc73 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 22:00:41 +0100 Subject: [PATCH 03/14] sqlite.Row type now implements GC protocol --- Modules/_sqlite/row.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index f9dfcbd5d615e5..d314c65370d34b 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -31,14 +31,27 @@ class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ -static void -pysqlite_row_dealloc(pysqlite_Row *self) +static int +row_clear(pysqlite_Row *self) { - PyTypeObject *tp = Py_TYPE(self); + Py_CLEAR(self->data); + Py_CLEAR(self->description); + return 0; +} - Py_XDECREF(self->data); - Py_XDECREF(self->description); +static int +row_traverse(pysqlite_Row *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} +static void +pysqlite_row_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -231,13 +244,15 @@ static PyType_Slot row_slots[] = { {Py_sq_length, pysqlite_row_length}, {Py_sq_item, pysqlite_row_item}, {Py_tp_new, pysqlite_row_new}, + {Py_tp_traverse, row_traverse}, + {Py_tp_clear, row_clear}, {0, NULL}, }; static PyType_Spec row_spec = { .name = MODULE_NAME ".Row", .basicsize = sizeof(pysqlite_Row), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = row_slots, }; From 4519017e100f2deed5db367c2e68ec3b2dcd657d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 22:01:55 +0100 Subject: [PATCH 04/14] sqlite.PrepareProtocol type now implements GC protocol --- Modules/_sqlite/prepare_protocol.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7d2d7ade591467..ece42f4df6f5ac 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -30,26 +30,33 @@ pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args, return 0; } +static int +pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self) { PyTypeObject *tp = Py_TYPE(self); - + PyObject_GC_UnTrack(self); tp->tp_free(self); Py_DECREF(tp); } static PyType_Slot type_slots[] = { {Py_tp_dealloc, pysqlite_prepare_protocol_dealloc}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_prepare_protocol_init}, + {Py_tp_traverse, pysqlite_prepare_protocol_traverse}, {0, NULL}, }; static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = type_slots, }; From 20da08820134d0d62882d20b13bb0d223af800f3 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 22:10:58 +0100 Subject: [PATCH 05/14] sqlite.Statement type now implements GC protocol --- Modules/_sqlite/connection.c | 2 +- Modules/_sqlite/cursor.c | 2 +- Modules/_sqlite/statement.c | 28 +++++++++++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 27d58dfc0060fa..0a3e55b6971818 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1351,7 +1351,7 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType); + statement = PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType); if (!statement) { return NULL; } diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 9861460ad80fe7..f1d1c8a1bbcf7d 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -506,7 +506,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, pysqlite_StatementType)); + PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType)); if (!self->statement) { goto error; } diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 57026270e1eeb5..358ee30074cb66 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -372,23 +372,36 @@ static void pysqlite_statement_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); Py_END_ALLOW_THREADS + self->st = NULL; } - self->st = NULL; - - Py_XDECREF(self->sql); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); +} +static int +stmt_clear(pysqlite_Statement *self) +{ + Py_CLEAR(self->sql); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} - tp->tp_free(self); - Py_DECREF(tp); +static int +stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) +{ + Py_VISIT(self->sql); + Py_VISIT(Py_TYPE(self)); + return 0; } /* @@ -468,14 +481,15 @@ static PyMemberDef stmt_members[] = { static PyType_Slot stmt_slots[] = { {Py_tp_members, stmt_members}, {Py_tp_dealloc, pysqlite_statement_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, stmt_traverse}, + {Py_tp_clear, stmt_clear}, {0, NULL}, }; static PyType_Spec stmt_spec = { .name = MODULE_NAME ".Statement", .basicsize = sizeof(pysqlite_Statement), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = stmt_slots, }; PyTypeObject *pysqlite_StatementType = NULL; From ca870ac061d15c98b365279e8faec8b0cd8633cf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 20 Jan 2021 22:13:12 +0100 Subject: [PATCH 06/14] sqlite3.Cache and sqlite3.Node types now implements GC protocol --- Modules/_sqlite/cache.c | 80 +++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 8da0a64a3f90a4..9e811cc6c0279d 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -44,14 +44,27 @@ pysqlite_new_node(PyObject *key, PyObject *data) return node; } +static int +node_traverse(pysqlite_Node *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +node_clear(pysqlite_Node *self) +{ + Py_CLEAR(self->key); + Py_CLEAR(self->data); + return 0; +} + static void pysqlite_node_dealloc(pysqlite_Node *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_DECREF(self->key); - Py_DECREF(self->data); - + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -88,31 +101,50 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs) return 0; } -static void -pysqlite_cache_dealloc(pysqlite_Cache *self) +static int +cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); - pysqlite_Node* node; - pysqlite_Node* delete_node; - - if (!self->factory) { - /* constructor failed, just get out of here */ - return; + pysqlite_Node *node = self->first; + while (node) { + Py_VISIT(node); + node = node->next; } + Py_VISIT(self->mapping); + if (self->decref_factory) { + Py_VISIT(self->factory); + } + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cache_clear(pysqlite_Cache *self) +{ /* iterate over all nodes and deallocate them */ - node = self->first; + pysqlite_Node *node = self->first; while (node) { - delete_node = node; + pysqlite_Node *delete_node = node; node = node->next; - Py_DECREF(delete_node); + Py_CLEAR(delete_node); } - if (self->decref_factory) { - Py_DECREF(self->factory); + Py_CLEAR(self->factory); + } + Py_CLEAR(self->mapping); + return 0; +} + +static void +pysqlite_cache_dealloc(pysqlite_Cache *self) +{ + if (!self->factory) { + /* constructor failed, just get out of here */ + return; } - Py_DECREF(self->mapping); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -260,14 +292,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args) static PyType_Slot node_slots[] = { {Py_tp_dealloc, pysqlite_node_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, node_traverse}, + {Py_tp_clear, node_clear}, {0, NULL}, }; static PyType_Spec node_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = node_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -283,15 +316,16 @@ static PyMethodDef cache_methods[] = { static PyType_Slot cache_slots[] = { {Py_tp_dealloc, pysqlite_cache_dealloc}, {Py_tp_methods, cache_methods}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cache_init}, + {Py_tp_traverse, cache_traverse}, + {Py_tp_clear, cache_clear}, {0, NULL}, }; static PyType_Spec cache_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cache_slots, }; PyTypeObject *pysqlite_CacheType = NULL; From f5d9873c22fb9608d5d1bf68dd1a027d6533829b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 13 May 2021 22:13:45 +0200 Subject: [PATCH 07/14] Remove unneeded self->db = NULL --- Modules/_sqlite/connection.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 0a3e55b6971818..f31342a8e8dcea 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -267,7 +267,6 @@ pysqlite_connection_dealloc(pysqlite_Connection *self) /* Clean up if user has not called .close() explicitly. */ if (self->db) { sqlite3_close_v2(self->db); - self->db = NULL; } tp->tp_free(self); From 34928edf7881738228751d70be95a51b8c62bfca Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 13 May 2021 22:15:42 +0200 Subject: [PATCH 08/14] Get rid of unneeded cast in cursor_dealloc --- Modules/_sqlite/cursor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index f1d1c8a1bbcf7d..b3e1ce2c04784b 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -116,11 +116,11 @@ cursor_clear(pysqlite_Cursor *self) } static void -cursor_dealloc(pysqlite_Cursor *self) +cursor_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - tp->tp_clear((PyObject *)self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } From 590ff8ed081de39bd217a59dbf60d64e4a4c3ef4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 23 May 2021 17:42:34 +0200 Subject: [PATCH 09/14] Address review: visit node->key, node->data, and con->isolation_level --- Modules/_sqlite/cache.c | 2 ++ Modules/_sqlite/connection.c | 1 + 2 files changed, 3 insertions(+) diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 9e811cc6c0279d..6d2b178cb7379b 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -47,6 +47,8 @@ pysqlite_new_node(PyObject *key, PyObject *data) static int node_traverse(pysqlite_Node *self, visitproc visit, void *arg) { + Py_VISIT(self->key); + Py_VISIT(self->data); Py_VISIT(Py_TYPE(self)); return 0; } diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index f31342a8e8dcea..accc573e72b08c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -229,6 +229,7 @@ static int connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) { Py_VISIT(self->statement_cache); + Py_VISIT(self->isolation_level); Py_VISIT(self->function_pinboard_trace_callback); Py_VISIT(self->function_pinboard_progress_handler); Py_VISIT(self->function_pinboard_authorizer_cb); From b080ff768ab4b5d76be3c182931dd8fec85b51fa Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 24 May 2021 09:07:51 +0200 Subject: [PATCH 10/14] Harden cache clear --- Modules/_sqlite/cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 6d2b178cb7379b..e0a1707348c912 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -124,6 +124,7 @@ cache_clear(pysqlite_Cache *self) { /* iterate over all nodes and deallocate them */ pysqlite_Node *node = self->first; + self->first = NULL; while (node) { pysqlite_Node *delete_node = node; node = node->next; From 2bcfa293b2792e79ea4bd83e43f0875111c2fd86 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 24 May 2021 23:44:53 +0200 Subject: [PATCH 11/14] Normalize connection_dealloc naming --- Modules/_sqlite/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index accc573e72b08c..47d97d17a91b98 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -259,7 +259,7 @@ connection_clear(pysqlite_Connection *self) } static void -pysqlite_connection_dealloc(pysqlite_Connection *self) +connection_dealloc(pysqlite_Connection *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); @@ -1932,7 +1932,7 @@ static struct PyMemberDef connection_members[] = }; static PyType_Slot connection_slots[] = { - {Py_tp_dealloc, pysqlite_connection_dealloc}, + {Py_tp_dealloc, connection_dealloc}, {Py_tp_doc, (void *)connection_doc}, {Py_tp_methods, connection_methods}, {Py_tp_members, connection_members}, From f8eb733c55de06f4c415dee0eecf2030a727d350 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 25 May 2021 08:36:44 +0200 Subject: [PATCH 12/14] Address review: visit row PyObjects for consistency --- Modules/_sqlite/row.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index d314c65370d34b..af8be803c805a5 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -42,6 +42,8 @@ row_clear(pysqlite_Row *self) static int row_traverse(pysqlite_Row *self, visitproc visit, void *arg) { + Py_VISIT(self->data); + Py_VISIT(self->description); Py_VISIT(Py_TYPE(self)); return 0; } From ab4c6e6903b16d84833de41aa8b5b774b7d562b5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 25 May 2021 08:37:34 +0200 Subject: [PATCH 13/14] Normalize statement dealloc naming --- Modules/_sqlite/statement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 358ee30074cb66..456342a7dfb944 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -369,7 +369,7 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) } static void -pysqlite_statement_dealloc(pysqlite_Statement *self) +stmt_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); @@ -480,7 +480,7 @@ static PyMemberDef stmt_members[] = { }; static PyType_Slot stmt_slots[] = { {Py_tp_members, stmt_members}, - {Py_tp_dealloc, pysqlite_statement_dealloc}, + {Py_tp_dealloc, stmt_dealloc}, {Py_tp_traverse, stmt_traverse}, {Py_tp_clear, stmt_clear}, {0, NULL}, From 926787d930b978229e085437a081a6018d252ecc Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 25 May 2021 08:43:44 +0200 Subject: [PATCH 14/14] Clear sqlite3 stmt resources in stmt_clear() --- Modules/_sqlite/statement.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 456342a7dfb944..3be12c79b47d9a 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -373,14 +373,6 @@ stmt_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - - if (self->st) { - Py_BEGIN_ALLOW_THREADS - sqlite3_finalize(self->st); - Py_END_ALLOW_THREADS - self->st = NULL; - } - tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); @@ -389,6 +381,13 @@ stmt_dealloc(pysqlite_Statement *self) static int stmt_clear(pysqlite_Statement *self) { + if (self->st) { + Py_BEGIN_ALLOW_THREADS + sqlite3_finalize(self->st); + Py_END_ALLOW_THREADS + self->st = 0; + } + Py_CLEAR(self->sql); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self);