Index: Modules/cPickle.c =================================================================== --- Modules/cPickle.c (revision 64527) +++ Modules/cPickle.c (working copy) @@ -339,7 +339,6 @@ int bin; int fast; /* Fast mode doesn't save in memo, don't use if circ ref */ - int nesting; int (*write_func)(struct Picklerobject *, const char *, Py_ssize_t); char *write_buf; int buf_size; @@ -1630,7 +1629,12 @@ iter = PyObject_GetIter(args); if (iter == NULL) goto finally; - res = batch_list(self, iter); + + if (Py_EnterRecursiveCall(" while pickling an object") == 0) + { + res = batch_list(self, iter); + Py_LeaveRecursiveCall(); + } Py_DECREF(iter); finally: @@ -1786,7 +1790,11 @@ iter = PyObject_CallMethod(args, "iteritems", "()"); if (iter == NULL) goto finally; - res = batch_dict(self, iter); + if (Py_EnterRecursiveCall(" while pickling an object") == 0) + { + res = batch_dict(self, iter); + Py_LeaveRecursiveCall(); + } Py_DECREF(iter); finally: @@ -2306,11 +2314,8 @@ int res = -1; int tmp, size; - if (self->nesting++ > Py_GetRecursionLimit()){ - PyErr_SetString(PyExc_RuntimeError, - "maximum recursion depth exceeded"); - goto finally; - } + if (Py_EnterRecursiveCall(" while pickling an object")) + return -1; if (!pers_save && self->pers_func) { if ((tmp = save_pers(self, args, self->pers_func)) != 0) { @@ -2559,7 +2564,7 @@ res = save_reduce(self, t, args); finally: - self->nesting--; + Py_LeaveRecursiveCall(); Py_XDECREF(py_ob_id); Py_XDECREF(__reduce__); Py_XDECREF(t); @@ -2801,7 +2806,6 @@ self->inst_pers_func = NULL; self->write_buf = NULL; self->fast = 0; - self->nesting = 0; self->fast_container = 0; self->fast_memo = NULL; self->buf_size = 0; Index: Lib/test/test_cpickle.py =================================================================== --- Lib/test/test_cpickle.py (revision 64527) +++ Lib/test/test_cpickle.py (working copy) @@ -96,21 +96,19 @@ class cPickleDeepRecursive(unittest.TestCase): # I commented out, because the patch that fixes this was reverted, as # it broke the next test case. Check the issues for full history. -# def test_issue2702(self): -# '''This should raise a RecursionLimit but in some -# platforms (FreeBSD, win32) sometimes raises KeyError instead, -# or just silently terminates the interpreter (=crashes). -# ''' -# nodes = [Node() for i in range(500)] -# for n in nodes: -# n.connections = list(nodes) -# n.connections.remove(n) -# self.assertRaises(RuntimeError, cPickle.dumps, n) + def test_issue2702(self): + # This should raise a RecursionLimit but in some + # platforms (FreeBSD, win32) sometimes raises KeyError instead, + # or just silently terminates the interpreter (=crashes). + nodes = [Node() for i in range(500)] + for n in nodes: + n.connections = list(nodes) + n.connections.remove(n) + self.assertRaises(RuntimeError, cPickle.dumps, n) def test_issue3179(self): - '''Safe test, because of I broken this case when fixing the - behaviour for the previous test. - ''' + # Safe test, because I broke this case when fixing the + # behaviour for the previous test. res=[] for x in range(1,2000): res.append(dict(doc=x, similar=[]))