Commit 4d2dcc93 authored by KIMURA Chikahiro's avatar KIMURA Chikahiro Committed by Jason Madden

Fix possibility of rare crash during dealloc. Fixes #66

parent 740e1d42
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
4.2.5 (unreleased) 4.2.5 (unreleased)
------------------ ------------------
- Nothing changed yet. - Fix the possibility of a rare crash in the C extension when
deallocating items. See https://github.com/zopefoundation/persistent/issues/66
4.2.4.2 (2017-04-23) 4.2.4.2 (2017-04-23)
......
...@@ -783,6 +783,7 @@ Per__getstate__(cPersistentObject *self) ...@@ -783,6 +783,7 @@ Per__getstate__(cPersistentObject *self)
static void static void
Per_dealloc(cPersistentObject *self) Per_dealloc(cPersistentObject *self)
{ {
PyObject_GC_UnTrack((PyObject *)self);
if (self->state >= 0) if (self->state >= 0)
{ {
/* If the cache has been cleared, then a non-ghost object /* If the cache has been cleared, then a non-ghost object
......
...@@ -206,7 +206,7 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes) ...@@ -206,7 +206,7 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes)
{ {
assert(self->ring_lock); assert(self->ring_lock);
assert(here != &self->ring_home); assert(here != &self->ring_home);
/* At this point we know that the ring only contains nodes /* At this point we know that the ring only contains nodes
from persistent objects, plus our own home node. We know from persistent objects, plus our own home node. We know
this because the ring lock is held. We can safely assume this because the ring lock is held. We can safely assume
...@@ -214,14 +214,14 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes) ...@@ -214,14 +214,14 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes)
is not the home */ is not the home */
object = OBJECT_FROM_RING(self, here); object = OBJECT_FROM_RING(self, here);
if (object->state == cPersistent_UPTODATE_STATE) if (object->state == cPersistent_UPTODATE_STATE)
{ {
CPersistentRing placeholder; CPersistentRing placeholder;
PyObject *method; PyObject *method;
PyObject *temp; PyObject *temp;
int error_occurred = 0; int error_occurred = 0;
/* deactivate it. This is the main memory saver. */ /* deactivate it. This is the main memory saver. */
/* Add a placeholder, a dummy node in the ring. We need /* Add a placeholder, a dummy node in the ring. We need
to do this to mark our position in the ring. It is to do this to mark our position in the ring. It is
possible that the PyObject_GetAttr() call below will possible that the PyObject_GetAttr() call below will
...@@ -237,7 +237,7 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes) ...@@ -237,7 +237,7 @@ scan_gc_items(ccobject *self, int target, Py_ssize_t target_bytes)
method = PyObject_GetAttr((PyObject *)object, py__p_deactivate); method = PyObject_GetAttr((PyObject *)object, py__p_deactivate);
if (method == NULL) if (method == NULL)
error_occurred = 1; error_occurred = 1;
else else
{ {
temp = PyObject_CallObject(method, NULL); temp = PyObject_CallObject(method, NULL);
Py_DECREF(method); Py_DECREF(method);
...@@ -891,6 +891,7 @@ cc_init(ccobject *self, PyObject *args, PyObject *kwds) ...@@ -891,6 +891,7 @@ cc_init(ccobject *self, PyObject *args, PyObject *kwds)
static void static void
cc_dealloc(ccobject *self) cc_dealloc(ccobject *self)
{ {
PyObject_GC_UnTrack((PyObject *)self);
Py_XDECREF(self->data); Py_XDECREF(self->data);
Py_XDECREF(self->jar); Py_XDECREF(self->jar);
PyObject_GC_Del(self); PyObject_GC_Del(self);
...@@ -1058,7 +1059,7 @@ cc_add_item(ccobject *self, PyObject *key, PyObject *v) ...@@ -1058,7 +1059,7 @@ cc_add_item(ccobject *self, PyObject *key, PyObject *v)
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"Cached object oid must be bytes, not a %s", "Cached object oid must be bytes, not a %s",
oid->ob_type->tp_name); oid->ob_type->tp_name);
return -1; return -1;
} }
......
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