[ZODB-Dev] Race condition in Connection.close

Marius Gedminas mgedmin at b4net.lt
Wed Apr 7 14:35:37 EDT 2004


I think I found a race condition in Connection.close in the current ZODB
3 CVS:

    # ZODB/Connection.py
    ...
    class Connection(...):
        ...
        def close(self):
            ...

            # Return the connection to the pool.
            if self._db is not None:
                self._db._closeConnection(self)             # 1
                self._db = None                             # 2

Assigning to self._db happens after self has been added to the
connection pool.  If another thread gets scheduled between points 1 and
2, it might have already started using this connection.

The race manifests with occasional AttributeErrors in Connection._setDB
or Connection.tpc_finish when I run SchoolTool (www.schooltool.org)
functional tests:

...
  File "src/schooltool/main.py", line 347, in _process
    self.zodb_conn = self.site.db.open()
  File "/home/mg/schooltool/src/ZODB/DB.py", line 514, in open
    c._setDB(self)
  File "/home/mg/schooltool/src/ZODB/Connection.py", line 354, in _setDB
    self._db.classFactory)
exceptions.AttributeError: 'NoneType' object has no attribute 'classFactory'

...
  File "src/schooltool/main.py", line 355, in _process
    txn.commit()
  File "/home/mg/schooltool/src/ZODB/Transaction.py", line 257, in commit
    self._cleanup(objects, ncommitted, jars, subjars)
  File "/home/mg/schooltool/src/ZODB/Transaction.py", line 253, in commit
    self._finish_one(jars[0])
  File "/home/mg/schooltool/src/ZODB/Transaction.py", line 362, in _finish_one
    jar.tpc_finish(self)
  File "/home/mg/schooltool/src/ZODB/Connection.py", line 936, in tpc_finish
    self._storage.tpc_finish(transaction, callback)
  File "/home/mg/schooltool/src/ZODB/BaseStorage.py", line 250, in tpc_finish
    f(self._tid)
  File "/home/mg/schooltool/src/ZODB/Connection.py", line 935, in callback
    self._db.invalidate(tid, d, self)
exceptions.AttributeError: 'NoneType' object has no attribute 'invalidate'


The line numbers might be slightly wrong since I added some debugging
code to Connection.py, and hadn't updated to the very last CVS version
before debugging this problem.  However the relevant part of
Connection.close is not changed in the latest CVS.

I'll try testing the obvious fix tomorrow and see if this fixes the
errors I saw.

            # Return the connection to the pool.
            if self._db is not None:
                db = self._db
                self._db = None
                db._closeConnection(self)

Marius Gedminas
-- 
"What's the name of the new OO COBOL -- an equivalent of C++?"
"ADD 1 TO COBOL GIVING COBOL"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zodb-dev/attachments/20040407/2b285b32/attachment.bin


More information about the ZODB-Dev mailing list