Re: psycopg2 2.0.8 - segmentation fault

"Gangadharan S.A." <[email protected]>
Newsgroups gmane.comp.python.db.psycopg.devel
Message-ID <[email protected]>
> Have attached the script to reproduce this issue and the one line fix for
> it.


Oops, missed the attachement. Here it is now.

Thanks,
Gangadharan

_______________________________________________
Psycopg mailing list
Psycopg-IAPFreCvJWPBWskQ1e/[email protected]
http://lists.initd.org/mailman/listinfo/psycopg
cursor_dealloc_fix.diff (text/x-diff, 329 B)
=== modified file 'psycopg/cursor_type.c'
--- psycopg/cursor_type.c	2009-02-07 17:02:14 +0000
+++ psycopg/cursor_type.c	2009-04-19 19:15:49 +0000
@@ -1718,6 +1718,8 @@
 {
     cursorObject *self = (cursorObject *)obj;
 
+    PyObject_GC_UnTrack(self);
+
     if (self->name) PyMem_Free(self->name);
 
     Py_CLEAR(self->conn);
trigger_cursor_double_dealloc.py (text/x-python, 2 KB)
import gc
import psycopg2
import psycopg2.extensions
import threading
import sys
import time
import thread

# double deallocs on cursor objects do not always have
# an immediately visible impact on the program as most of the
# steps in the dealloc are idempotent.
# But eventually, when we free something a second time, it will
# have already been allocated to some one else.

# inherit psycopg2 cursor class just so that
# garbage collector enters the tp_clear code path
# in delete_garbage()
class my_cursor(psycopg2.extensions.cursor):
    pass

class db_user(threading.Thread):
    def run(self):
        global done
        global lock
        for i in range(1000):
            print >> sys.stderr, "start db user iteration %d" % (i,)
            connection = psycopg2.connect(sys.argv[1])
            cursor = connection.cursor(cursor_factory=my_cursor)
            cursor.execute("SELECT 1")

            # this del call will not deallocate the connection
            # the connection will still be kept alive by
            # the reference from cursor
            del connection

            # maximize gc-dealloc concurrency probablity by
            # allowing gc to run only during cursor/connection dealloc
            lock.release()
            print >> sys.stderr, "del cursor %d begin" % (i,)

            # this call will dealloc cursor which will dealloc the connection
            # from inside. connection dealloc will release GIL temporarily,
            # giving a chance for the other thread to invoke garbage collection
            del cursor
            lock.acquire()
            print >> sys.stderr, "end db user iteration %d" % (i,)
        done = True

if __name__ == '__main__':
    lock = thread.allocate_lock()
    lock.acquire()
    done = False
    db_user().start()
    j = 0
    while not done:
        lock.acquire()
        print >> sys.stderr, "going to run gc %d" % (j, )
        print "gc result: %d" % (gc.collect(), )
        print >> sys.stderr, "ran gc %d" % (j, )
        lock.release()
        time.sleep(.000001) # avoid busy loop
        j += 1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.