The following code crashes:
import sqlite3
import weakref
def callback(*args):
pass
connection = sqlite3.connect(":memory:")
cursor = sqlite3.Cursor(connection)
ref = weakref.ref(cursor, callback)
cursor.__init__(connection)
del cursor
del ref
IIUC, this is because pysqlite_cursor_init() (in Modules/_sqlite/cursor.c) sets
`self->in_weakreflist` to NULL, and thus corrupts the weakref list. Later,
clear_weakref() (in Objects/weakrefobject.c) tries to remove a reference from
the corrupted list, and crashes.
In every other place (that i saw) where such a weakreflist field is used, it is
set to NULL right after allocating the object (usually in __new__()), or just
not set at all, e.g. in `functools.partial`.
So since PyType_GenericNew() is the __new__() of sqlite3.Cursor, ISTM that the
simplest solution is to not touch `self->in_weakreflist` at all in
pysqlite_cursor_init().
Also, the following code results in refleaks:
import sys
import sqlite3
connection = sqlite3.connect(":memory:")
cursor = sqlite3.Cursor(connection)
refcount_before = sys.gettotalrefcount()
cursor.__init__(connection)
print(sys.gettotalrefcount() - refcount_before) # should be close to 0
This is because pysqlite_cursor_init() doesn't decref before assigning to
fields of `self`.
I would open a PR to fix this soon.