summaryrefslogtreecommitdiff
path: root/sandbox/trigger_double_dealloc.py
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/trigger_double_dealloc.py')
-rw-r--r--sandbox/trigger_double_dealloc.py63
1 files changed, 0 insertions, 63 deletions
diff --git a/sandbox/trigger_double_dealloc.py b/sandbox/trigger_double_dealloc.py
deleted file mode 100644
index 1312aa3..0000000
--- a/sandbox/trigger_double_dealloc.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from __future__ import print_function
-
-import psycopg2, psycopg2.extensions
-import threading
-import gc
-import time
-import sys
-
-# inherit psycopg2 connection class just so that
-# garbage collector enters the tp_clear code path
-# in delete_garbage()
-
-class my_connection(psycopg2.extensions.connection):
- pass
-
-class db_user(threading.Thread):
- def run(self):
- conn2 = psycopg2.connect(sys.argv[1], connection_factory=my_connection)
- cursor = conn2.cursor()
- cursor.execute("UPDATE test_psycopg2_dealloc SET a = 3", async=1)
-
- # the conn2 desctructor will block indefinitely
- # on the completion of the query
- # (and it will not be holding the GIL during that time)
- print("begin conn2 del", file=sys.stderr)
- del cursor, conn2
- print("end conn2 del", file=sys.stderr)
-
-def main():
- # lock out a db row
- conn1 = psycopg2.connect(sys.argv[1], connection_factory=my_connection)
- cursor = conn1.cursor()
- cursor.execute("DROP TABLE IF EXISTS test_psycopg2_dealloc")
- cursor.execute("CREATE TABLE test_psycopg2_dealloc (a int)")
- cursor.execute("INSERT INTO test_psycopg2_dealloc VALUES (1)")
- conn1.commit()
- cursor.execute("UPDATE test_psycopg2_dealloc SET a = 2", async=1)
-
- # concurrent thread trying to access the locked row
- db_user().start()
-
- # eventually, a gc.collect run will happen
- # while the conn2 is inside conn_close()
- # but this second dealloc won't get blocked
- # as it will avoid conn_close()
- for i in range(10):
- if gc.collect():
- print("garbage collection done", file=sys.stderr)
- break
- time.sleep(1)
-
- # we now unlock the row by invoking
- # the desctructor of conn1. This will permit the
- # concurrent thread destructor of conn2 to
- # continue and it will end up trying to free
- # self->dsn a second time.
- print("begin conn1 del", file=sys.stderr)
- del cursor, conn1
- print("end conn1 del", file=sys.stderr)
-
-
-if __name__ == '__main__':
- main()