Commit 8bf8f23b authored by Kirill Smelkov's avatar Kirill Smelkov

X bigfile/_file_zodb: Fix logic around ZSync usage

The logic inside ZSync was correct, but it was incorrect to attach zsync
to zconn to stay alive and react when that zconn is garbage collected:
zsync._on_zconn_dealloc was not called because zsync itself was garbage
collected too.

This fixes many failures where wconn and associated pinner was not
released even though ZODB DB was correctly closed.
parent 3a6bd764
......@@ -58,6 +58,7 @@ from cpython cimport PyCapsule_New
from ZODB.Connection import Connection as ZConnection
from ZODB.utils import u64
from wendelin.lib.zodb import zconn_at
from golang import sync as pysync
import weakref
......@@ -147,7 +148,7 @@ cdef wcfs.PyConn pywconnOf(zconn):
zconn._wcfs_wconn = wconn
# keep wconn view of the database in sync with zconn
zconn._wcfs_wconn_zsync = ZSync(zconn, wconn)
ZSync(zconn, wconn)
return wconn
......@@ -156,6 +157,10 @@ cdef wcfs.PyConn pywconnOf(zconn):
#
# wconn will be closed once zconn is destroyed (not closed, which returns it
# back into DB pool).
#
# ZSync cares itself to stay alive as long as zconn stays alive.
_zsyncRegMu = pysync.Mutex()
_zsyncReg = {} # id(zsync) -> zsync
class ZSync:
# .zconn_ref weakref[zodb.Connection]
# .wconn (py) wcfs.Connection
......@@ -172,9 +177,15 @@ class ZSync:
# tm.commit() # zconn.at updated again
zconn.onResyncCallback(zsync)
# .zconn dealloc -> wconn.close
# keep zsync in _zsyncReg for zsync to stay alive independently of the caller.
with _zsyncRegMu:
_zsyncReg[id(zsync)] = zsync
# .zconn dealloc -> wconn.close; release zsync
def on_zconn_dealloc(zsync, _):
zsync.wconn.close()
with _zsyncRegMu:
del _zsyncReg[id(zsync)]
# DB resyncs .zconn onto new database view.
# -> resync .wconn to updated database view of ZODB connection.
......
......@@ -56,8 +56,8 @@ def test_zsync():
defer(wc.close)
wconn = wc.connect(at0)
assert wconn.at() == at0
# setup ZSync for wconn <-> zconn
zsync = ZSync(zconn, wconn)
# setup ZSync for wconn <-> zconn; don't keep zsync explicitly referenced
ZSync(zconn, wconn)
assert wconn.at() == at0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment