Author zzzeek
Recipients zzzeek
Date 2021-06-03.18:23:06
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1622744587.51.0.457614596671.issue44304@roundup.psfhosted.org>
In-reply-to
Content
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()
History
Date User Action Args
2021-06-03 18:23:07zzzeeksetrecipients: + zzzeek
2021-06-03 18:23:07zzzeeksetmessageid: <1622744587.51.0.457614596671.issue44304@roundup.psfhosted.org>
2021-06-03 18:23:07zzzeeklinkissue44304 messages
2021-06-03 18:23:06zzzeekcreate