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