diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 2003546ce84cef..28eb1628384ac1 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1884,8 +1884,9 @@ static PyObject * chain_next(PyObject *op) { chainobject *lz = chainobject_CAST(op); - PyObject *item; + PyObject *item = NULL; + Py_BEGIN_CRITICAL_SECTION(op); /* lz->source is the iterator of iterables. If it's NULL, we've already * consumed them all. lz->active is the current iterator. If it's NULL, * we should grab a new one from lz->source. */ @@ -1894,31 +1895,38 @@ chain_next(PyObject *op) PyObject *iterable = PyIter_Next(lz->source); if (iterable == NULL) { Py_CLEAR(lz->source); - return NULL; /* no more input sources */ + goto exit; /* no more input sources */ } lz->active = PyObject_GetIter(iterable); Py_DECREF(iterable); if (lz->active == NULL) { Py_CLEAR(lz->source); - return NULL; /* input not iterable */ + goto exit; /* input not iterable */ } } item = (*Py_TYPE(lz->active)->tp_iternext)(lz->active); - if (item != NULL) - return item; + if (item != NULL) { + goto exit; + } if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); - else - return NULL; /* input raised an exception */ + else { + goto exit; /* input raised an exception */ + } } /* lz->active is consumed, try with the next iterable. */ Py_CLEAR(lz->active); } /* Everything had been consumed already. */ - return NULL; + +exit: + Py_END_CRITICAL_SECTION() + + return item; } + PyDoc_STRVAR(chain_doc, "chain(*iterables)\n\ --\n\