Message395028
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
# don't del the exception context is necessary
# 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)
# raising exception is necessary
raise Exception("this is a test")
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() |
|
Date |
User |
Action |
Args |
2021-06-03 18:23:07 | zzzeek | set | recipients:
+ zzzeek |
2021-06-03 18:23:07 | zzzeek | set | messageid: <1622744587.51.0.457614596671.issue44304@roundup.psfhosted.org> |
2021-06-03 18:23:07 | zzzeek | link | issue44304 messages |
2021-06-03 18:23:06 | zzzeek | create | |
|