""" A script to reproduce the race condition described in ticket #58 from https://bugzilla.redhat.com/show_bug.cgi?id=711095 Results in the error: python: Modules/gcmodule.c:277: visit_decref: Assertion `gc->gc.gc_refs != 0' failed. on unpatched library. """ import threading import gc import time import psycopg2 from StringIO import StringIO done = 0 class GCThread(threading.Thread): # A thread that sits in an infinite loop, forcing the garbage collector # to run def run(self): global done while not done: gc.collect() time.sleep(0.1) # give the other thread a chance to run gc_thread = GCThread() # This assumes a pre-existing db named "test", with: # "CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);" conn = psycopg2.connect("dbname=test user=postgres") cur = conn.cursor() # Start the other thread, running the GC regularly gc_thread.start() # Now do lots of "cursor.copy_from" calls: print("copy_from") for i in range(1000): f = StringIO("42\tfoo\n74\tbar\n") cur.copy_from(f, 'test', columns=('num', 'data')) # Assuming the other thread gets a chance to run during this call, expect a # build of python (with assertions enabled) to bail out here with: # python: Modules/gcmodule.c:277: visit_decref: Assertion `gc->gc.gc_refs != 0' failed. # Also exercise the copy_to code path print("copy_to") cur.execute("truncate test") f = StringIO("42\tfoo\n74\tbar\n") cur.copy_from(f, 'test', columns=('num', 'data')) for i in range(1000): f = StringIO() cur.copy_to(f, 'test', columns=('num', 'data')) # And copy_expert too print("copy_expert") cur.execute("truncate test") for i in range(1000): f = StringIO("42\tfoo\n74\tbar\n") cur.copy_expert("copy test to stdout", f) # Terminate the GC thread's loop: done = 1 cur.close() conn.close()