-
-
Notifications
You must be signed in to change notification settings - Fork 30.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
segmentation fault appeared in python 3.10.0b2 #88470
Comments
segmentation fault related to object deallocation and traceback objects, is extremely difficult to reproduce and definitely appeared as of 3.10.0b2, does not occur in 3.10.0b1. linux and osx platforms are affected. The issue requires "greenlet==1.1.0" to be installed, as well as that for me to reproduce it I have to use sqlite3 with some special APIs also, so while this issue might be in greenlet, or sqlite3, I have a feeling these are all factors that are combining together in a very random way to reveal something that's actually happening in the interpreter, but in any case would be great if core devs can see why it happens. The below script has been tested on various linux platforms, and the overall bug was revealed by an interaction in the SQLAlchemy test suite that's occurring in many places including OSX, linux. As noted, a whole bunch of very random things are needed for me to reproduce it. import greenlet
import sqlite3
class _ErrorContainer(object):
error = None
def _expect_raises_fn(fn):
ec = _ErrorContainer()
try:
fn()
except Exception as err:
assert str(err) == "this is a test"
# assign the exception context outside of the except
# is necessary
ec.error = err
# del ec def greenlet_spawn(fn, *args, **kwargs):
# spawning a greenlet is necessary
context = greenlet.greenlet(fn, greenlet.getcurrent())
# assignment to "result" is necessary
result = context.switch(*args, **kwargs)
class OuterConnectionWrapper:
def __init__(self, connection):
self.connection = connection
def go(self, stmt):
sqlite_connection = self.connection
cursor = sqlite_connection.cursor()
cursor.execute("select 1")
return cursor
def execute(self, stmt):
return greenlet_spawn(self.go, stmt)
def _do_close(self):
self.connection.close()
self.connection = None
def close(self):
self._do_close()
class InnerConnectionWrapper:
def __init__(self, connection):
self.connection = connection
def create_function(self, *arg, **kw):
self.connection.create_function(*arg, **kw)
def cursor(self):
return self.connection.cursor()
def close(self):
self.connection = None
class ConnectionPool:
def __init__(self):
self.conn = sqlite3.connect(":memory:")
def regexp(a, b):
return None
self.conn.create_function("regexp", 2, regexp)
def connect(self):
return InnerConnectionWrapper(self.conn)
def do_test():
pool = ConnectionPool()
def go():
c1 = pool.connect()
conn = OuterConnectionWrapper(c1)
try:
conn.execute("test")
finally:
conn.close()
_expect_raises_fn(go)
do_test() |
if the issue is in greenlet this can be bounced back to https://github.com/python-greenlet/greenlet/issues/242 |
Coredevs are likely to assume that the problem is in greenlets, especially if it has any C code (I don't know). I suggest you first try to find the commit between releases that resulted in the problem. If it is not deterministicly reproducible, you likely need to do a manual binary search. (This is as much as I know.) If you get an OS 'traceback' longer than a dozen line or so, please attach it as a file rather than pasting in a message. |
yes, if I have time I will begin to undertake that, wanted to put it up here in case anyone has git bisect on speed dial for cpython. |
I did the bisection: ff359d7 is the first bad commit
:040000 040000 701f24eacbdf2b52b612dc33ae9a7dcf24a73826 100af9271a7e7c038a860388587b1cb096b8494f M Modules |
The problem is that this is wrong: cpython/Modules/_sqlite/statement.c Lines 411 to 423 in f171877
|
Using the reproducer code by Mike, without this fix: ❯ ./python ../lel.py With this fix: ❯ ./python ../problem.py |
This is a simpler reproducer: dest = sqlite.connect(':memory:')
def md5sum(t):
return
dest.create_function("md5", 1, md5sum)
x = dest("create table lang (name, first_appeared)")
del md5sum, dest
y = [x]
y.append(y)
|
Thanks Mike for the report and reproducer, and Pablo for the fix! |
great news! Based on how many random factors were needed to reproduce as well as that it seemed to be gc related and appeared very suddenly, I had an intuition this was on the cpython side, thanks so much for doing this Pablo! |
sqlit3.Cursor is prone to the same bug. Do you want me to create a new issue for it, or can I reuse this issue number, Pablo? I'll see if I can create a reproducer for that as well. |
No, is not: it doesn't drop the GIL in tp_clear. There is technically no bug, but is true that tp_clear should only clean Python references. Although in this case there are some sematics with the cleanup that are not clear. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: