Commit 13e8eb78 authored by Kirill Smelkov's avatar Kirill Smelkov

X catch simultaneous invalidate vs unghostify

This continues https://github.com/zopefoundation/zodb/commit/1e285a3c

It caught the following race condition on zopenrace.py[1] in ZODB4
environment(*):

    Exception in thread Thread-25:
    Traceback (most recent call last):
      File "/srv/slapgrid/slappart7/srv/runner/software/c75bac561a367d3162cc44818372d123/parts/python2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
        self.run()
      File "/srv/slapgrid/slappart7/srv/runner/software/c75bac561a367d3162cc44818372d123/parts/python2.7/lib/python2.7/threading.py", line 754, in run
        self.__target(*self.__args, **self.__kwargs)
      File "./zopenrace.py", line 160, in T1
        t1()
      File "./zopenrace.py", line 153, in t1
        raise AssertionError("T1: obj1.i (%d)  !=  obj2.i (%d)" % (i1, i2))
    AssertionError: T1: obj1.i (503)  !=  obj2.i (502)

    Exception in thread Thread-26:
    Traceback (most recent call last):
      File "/srv/slapgrid/slappart7/srv/runner/software/c75bac561a367d3162cc44818372d123/parts/python2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
        self.run()
      File "/srv/slapgrid/slappart7/srv/runner/software/c75bac561a367d3162cc44818372d123/parts/python2.7/lib/python2.7/threading.py", line 754, in run
        self.__target(*self.__args, **self.__kwargs)
      File "./zopenrace.py", line 184, in T2
        t2()
      File "./zopenrace.py", line 179, in t2
        transaction.commit()
      File "/srv/slapgrid/slappart7/srv/runner/kirr/JZ3.venv/lib/python2.7/site-packages/transaction/_manager.py", line 123, in commit
        return self.get().commit()
      File "/srv/slapgrid/slappart7/srv/runner/kirr/JZ3.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 285, in commit
        self._synchronizers.map(lambda s: s.afterCompletion(self))
      File "/srv/slapgrid/slappart7/srv/runner/kirr/JZ3.venv/lib/python2.7/site-packages/transaction/weakset.py", line 62, in map
        f(elt)
      File "/srv/slapgrid/slappart7/srv/runner/kirr/JZ3.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 285, in <lambda>
        self._synchronizers.map(lambda s: s.afterCompletion(self))
      File "/srv/slapgrid/slappart7/srv/runner/kirr/ZODB/src/ZODB/Connection.py", line 871, in _storage_sync
        self._flush_invalidations()
      File "/srv/slapgrid/slappart7/srv/runner/kirr/ZODB/src/ZODB/Connection.py", line 549, in _flush_invalidations
        self._cache.invalidate(invalidated)
    SystemError: invalidate: object at 0x7fa0cf1375f0 with type PInt:  simultaneous unghostify is running

[1] https://github.com/zopefoundation/ZODB/issues/290
(*) ZODB-4.4.4 + PR136 + ping-on-newtxn
parent 0e231fd3
......@@ -95,6 +95,7 @@ fatal_1350(cPersistentObject *self, const char *caller, const char *detail)
#endif
static void ghostify(cPersistentObject*);
static int _unghostify(cPersistentObject*);
static PyObject * pickle_slotnames(PyTypeObject *cls);
static PyObject * convert_name(PyObject *name);
......@@ -105,7 +106,28 @@ static PyObject * convert_name(PyObject *name);
static int
unghostify(cPersistentObject *self)
{
if (self->state < 0 && self->jar)
int ret;
if (self->state >= 0 || self->jar == NULL)
return 1;
if (self->xxx_in_unghostify) {
PyErr_Format(PyExc_SystemError, "object at %p with type %.200s: "
"double ghostify", self, Py_TYPE(self)->tp_name);
return -1;
}
self->xxx_in_unghostify = 1;
ret = _unghostify(self);
self->xxx_in_unghostify = 0;
return ret;
}
static int
_unghostify(cPersistentObject *self)
{
// if (self->state < 0 && self->jar)
if (1)
{
PyObject *r;
......@@ -366,6 +388,12 @@ Per__p_invalidate(cPersistentObject *self)
{
signed char old_state = self->state;
if (self->xxx_in_unghostify) {
PyErr_Format(PyExc_SystemError, "invalidate: object at %p with type %.200s: "
" simultaneous unghostify is running", self, Py_TYPE(self)->tp_name);
return NULL;
}
if (old_state != cPersistent_GHOST_STATE)
{
if (Per_set_changed(self, NULL) < 0)
......
......@@ -60,7 +60,8 @@ typedef struct ccobject_head_struct PerCache;
PerCache *cache; \
CPersistentRing ring; \
char serial[8]; \
signed state:8; \
signed state:7; \
unsigned xxx_in_unghostify:1; \
unsigned estimated_size:24;
/* We recently added estimated_size. We originally added it as a new
......
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