Skip to content

Commit 6f465f9

Browse files
author
Ahmed Magdy Ali
committed
gh-150505: Revert "fix data race in Unpickler_set_memo under free-threading"
1 parent 61839ca commit 6f465f9

3 files changed

Lines changed: 6 additions & 53 deletions

File tree

Lib/test/test_pickle.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from test import support
1818
from test.support import cpython_only, import_helper, os_helper
1919
from test.support.import_helper import ensure_lazy_imports
20-
from test.support import threading_helper
2120

2221
from test.pickletester import AbstractHookTests
2322
from test.pickletester import AbstractUnpickleTests
@@ -809,20 +808,6 @@ def test_unknown_flag(self):
809808
self.assertStartsWith(stderr.getvalue(), 'usage: ')
810809

811810

812-
class UnpicklerMemoThreadSafetyTest(unittest.TestCase):
813-
@unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled')
814-
@threading_helper.reap_threads
815-
@threading_helper.requires_working_threading()
816-
def test_memo_assignment_race(self):
817-
from threading import Thread
818-
shared = pickle.Unpickler(io.BytesIO(b''))
819-
def assign():
820-
for _ in range(10000):
821-
shared.memo = {j: j for j in range(100)}
822-
threads = [Thread(target=assign) for _ in range(8)]
823-
for t in threads: t.start()
824-
for t in threads: t.join()
825-
826811
def load_tests(loader, tests, pattern):
827812
tests.addTest(doctest.DocTestSuite(pickle))
828813
return tests

Misc/NEWS.d/next/Library/2026-05-28-11-46-23.gh-issue-150505.avtcRy.rst

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

Modules/_pickle.c

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7786,38 +7786,24 @@ Unpickler_set_memo(PyObject *op, PyObject *obj, void *Py_UNUSED(closure))
77867786
if (new_memo == NULL)
77877787
return -1;
77887788

7789-
bool goto_error = false;
7790-
Py_BEGIN_CRITICAL_SECTION(self);
77917789
while (PyDict_Next(obj, &i, &key, &value)) {
77927790
Py_ssize_t idx;
77937791
if (!PyLong_Check(key)) {
77947792
PyErr_SetString(PyExc_TypeError,
77957793
"memo key must be integers");
7796-
goto_error = true;
7797-
break;
7794+
goto error;
77987795
}
77997796
idx = PyLong_AsSsize_t(key);
7800-
if (idx == -1 && PyErr_Occurred()) {
7801-
goto_error = true;
7802-
break;
7803-
}
7797+
if (idx == -1 && PyErr_Occurred())
7798+
goto error;
78047799
if (idx < 0) {
78057800
PyErr_SetString(PyExc_ValueError,
78067801
"memo key must be positive integers.");
7807-
goto_error = true;
7808-
break;
7802+
goto error;
78097803
}
7810-
78117804
if (_Unpickler_MemoPut(self, idx, value) < 0)
7812-
{
7813-
goto_error = true;
7814-
break;
7815-
}
7805+
goto error;
78167806
}
7817-
Py_END_CRITICAL_SECTION();
7818-
if (goto_error)
7819-
goto error;
7820-
78217807
}
78227808
else {
78237809
PyErr_Format(PyExc_TypeError,
@@ -7826,24 +7812,9 @@ Unpickler_set_memo(PyObject *op, PyObject *obj, void *Py_UNUSED(closure))
78267812
return -1;
78277813
}
78287814

7829-
Py_ssize_t old_memo_size, i;
7830-
PyObject **old_memo;
7831-
7832-
Py_BEGIN_CRITICAL_SECTION(self);
7833-
old_memo_size = self->memo_size;
7834-
old_memo = self->memo;
7815+
_Unpickler_MemoCleanup(self);
78357816
self->memo_size = new_memo_size;
78367817
self->memo = new_memo;
7837-
Py_END_CRITICAL_SECTION();
7838-
7839-
if (old_memo == NULL) {
7840-
return 0;
7841-
}
7842-
i = old_memo_size;
7843-
while (--i >= 0) {
7844-
Py_XDECREF(old_memo[i]);
7845-
}
7846-
PyMem_Free(old_memo);
78477818

78487819
return 0;
78497820

0 commit comments

Comments
 (0)