Skip to content

Commit 0bd80a1

Browse files
authored
[3.14] Revert "[3.14] gh-146452: Improve locking granularity in pickle's batch_dict_… (#150062)" (#150263)
Revert "[3.14] gh-146452: Improve locking granularity in pickle's batch_dict_… (#150062)" This reverts commit 1243cd6.
1 parent 2dd91d2 commit 0bd80a1

2 files changed

Lines changed: 19 additions & 31 deletions

File tree

Misc/NEWS.d/next/Library/2026-05-18-15-30-34.gh-issue-146452.RM0EVJ.rst

Lines changed: 0 additions & 2 deletions
This file was deleted.

Modules/_pickle.c

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,12 +3351,9 @@ batch_dict(PickleState *state, PicklerObject *self, PyObject *iter, PyObject *or
33513351
* Returns 0 on success, -1 on error.
33523352
*
33533353
* Note that this currently doesn't work for protocol 0.
3354-
3355-
* gh-146452: Wrap the dict iteration in a critical sections to prevent
3356-
* concurrent mutation from invalidating PyDict_Next() iteration state.
33573354
*/
33583355
static int
3359-
batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
3356+
batch_dict_exact_impl(PickleState *state, PicklerObject *self, PyObject *obj)
33603357
{
33613358
PyObject *key = NULL, *value = NULL;
33623359
int i;
@@ -3373,19 +3370,9 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
33733370

33743371
/* Special-case len(d) == 1 to save space. */
33753372
if (dict_size == 1) {
3376-
int next;
3377-
Py_BEGIN_CRITICAL_SECTION(obj);
3378-
next = PyDict_Next(obj, &ppos, &key, &value);
3379-
if (next) {
3380-
Py_INCREF(key);
3381-
Py_INCREF(value);
3382-
}
3383-
Py_END_CRITICAL_SECTION();
3384-
if (!next) {
3385-
PyErr_SetString(PyExc_RuntimeError,
3386-
"dictionary changed size during iteration");
3387-
goto error;
3388-
}
3373+
PyDict_Next(obj, &ppos, &key, &value);
3374+
Py_INCREF(key);
3375+
Py_INCREF(value);
33893376
if (save(state, self, key, 0) < 0) {
33903377
goto error;
33913378
}
@@ -3405,18 +3392,9 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
34053392
i = 0;
34063393
if (_Pickler_Write(self, &mark_op, 1) < 0)
34073394
return -1;
3408-
int next;
3409-
while (1) {
3410-
Py_BEGIN_CRITICAL_SECTION(obj);
3411-
next = PyDict_Next(obj, &ppos, &key, &value);
3412-
if (next) {
3413-
Py_INCREF(key);
3414-
Py_INCREF(value);
3415-
}
3416-
Py_END_CRITICAL_SECTION();
3417-
if (!next) {
3418-
break;
3419-
}
3395+
while (PyDict_Next(obj, &ppos, &key, &value)) {
3396+
Py_INCREF(key);
3397+
Py_INCREF(value);
34203398
if (save(state, self, key, 0) < 0) {
34213399
goto error;
34223400
}
@@ -3446,6 +3424,18 @@ batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
34463424
return -1;
34473425
}
34483426

3427+
/* gh-146452: Wrap the dict iteration in a critical section to prevent
3428+
concurrent mutation from invalidating PyDict_Next() iteration state. */
3429+
static int
3430+
batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
3431+
{
3432+
int ret;
3433+
Py_BEGIN_CRITICAL_SECTION(obj);
3434+
ret = batch_dict_exact_impl(state, self, obj);
3435+
Py_END_CRITICAL_SECTION();
3436+
return ret;
3437+
}
3438+
34493439
static int
34503440
save_dict(PickleState *state, PicklerObject *self, PyObject *obj)
34513441
{

0 commit comments

Comments
 (0)