Skip to content

Commit 4bf573e

Browse files
use critical section on iterator
1 parent 473cfa0 commit 4bf573e

1 file changed

Lines changed: 20 additions & 12 deletions

File tree

Objects/odictobject.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,7 @@ odict_tp_clear(PyObject *op)
14751475
{
14761476
PyODictObject *od = _PyODictObject_CAST(op);
14771477
Py_CLEAR(od->od_inst_dict);
1478-
PyDict_Clear((PyObject *)od);
1478+
_PyDict_Clear_LockHeld((PyObject *)od);
14791479
_odict_clear_nodes(od);
14801480
return 0;
14811481
}
@@ -1721,13 +1721,12 @@ odictiter_traverse(PyObject *op, visitproc visit, void *arg)
17211721
static PyObject *
17221722
odictiter_nextkey_lock_held(odictiterobject *di)
17231723
{
1724+
assert(di->di_odict != NULL);
17241725
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
17251726
PyObject *key = NULL;
17261727
_ODictNode *node;
17271728
int reversed = di->kind & _odict_ITER_REVERSED;
17281729

1729-
if (di->di_odict == NULL)
1730-
return NULL;
17311730
if (di->di_current == NULL)
17321731
goto done; /* We're already done. */
17331732

@@ -1768,18 +1767,31 @@ odictiter_nextkey_lock_held(odictiterobject *di)
17681767
return key;
17691768

17701769
done:
1771-
#ifndef Py_GIL_DISABLED
17721770
Py_CLEAR(di->di_odict);
1773-
#endif
17741771
return key;
17751772
}
17761773

1774+
1775+
static PyObject *
1776+
odictiter_nextkey(odictiterobject *di)
1777+
{
1778+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1779+
if (di->di_odict == NULL) {
1780+
return NULL;
1781+
}
1782+
PyObject *res;
1783+
Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1784+
res = odictiter_nextkey_lock_held(di);
1785+
Py_END_CRITICAL_SECTION();
1786+
return res;
1787+
}
1788+
17771789
static PyObject *
17781790
odictiter_iternext_lock_held(PyObject *op)
17791791
{
17801792
odictiterobject *di = (odictiterobject*)op;
17811793
PyObject *result, *value;
1782-
PyObject *key = odictiter_nextkey_lock_held(di); /* new reference */
1794+
PyObject *key = odictiter_nextkey(di); /* new reference */
17831795

17841796
if (key == NULL)
17851797
return NULL;
@@ -1789,14 +1801,12 @@ odictiter_iternext_lock_held(PyObject *op)
17891801
return key;
17901802
}
17911803

1792-
value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1793-
if (value == NULL) {
1804+
if (PyDict_GetItemRef((PyObject *)di->di_odict, key, &value) != 1) {
17941805
if (!PyErr_Occurred())
17951806
PyErr_SetObject(PyExc_KeyError, key);
17961807
Py_DECREF(key);
17971808
goto done;
17981809
}
1799-
Py_INCREF(value);
18001810

18011811
/* Handle the values case. */
18021812
if (!(di->kind & _odict_ITER_KEYS)) {
@@ -1832,17 +1842,15 @@ odictiter_iternext_lock_held(PyObject *op)
18321842

18331843
done:
18341844
Py_CLEAR(di->di_current);
1835-
#ifndef Py_GIL_DISABLED
18361845
Py_CLEAR(di->di_odict);
1837-
#endif
18381846
return NULL;
18391847
}
18401848

18411849
static PyObject *
18421850
odictiter_iternext(PyObject *op)
18431851
{
18441852
PyObject *res;
1845-
Py_BEGIN_CRITICAL_SECTION(((odictiterobject*)op)->di_odict);
1853+
Py_BEGIN_CRITICAL_SECTION(op);
18461854
res = odictiter_iternext_lock_held(op);
18471855
Py_END_CRITICAL_SECTION();
18481856
return res;

0 commit comments

Comments
 (0)