mirror of
https://github.com/python/cpython.git
synced 2025-10-21 14:12:27 +00:00
gh-112069: Add _PySet_NextEntryRef to be thread-safe. (gh-117990)
This commit is contained in:
parent
40f4d641a9
commit
94444ea45a
9 changed files with 76 additions and 34 deletions
|
@ -862,7 +862,7 @@ subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
|
|||
|
||||
// Make a local copy of the registry to protect against concurrent
|
||||
// modifications of _abc_registry.
|
||||
PyObject *registry = PySet_New(registry_shared);
|
||||
PyObject *registry = PyFrozenSet_New(registry_shared);
|
||||
if (registry == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -9,15 +9,16 @@
|
|||
#endif
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_bytesobject.h" // _PyBytesWriter
|
||||
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
|
||||
#include "pycore_long.h" // _PyLong_AsByteArray()
|
||||
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
||||
#include "pycore_object.h" // _PyNone_Type
|
||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||
#include "pycore_runtime.h" // _Py_ID()
|
||||
#include "pycore_setobject.h" // _PySet_NextEntry()
|
||||
#include "pycore_sysmodule.h" // _PySys_GetAttr()
|
||||
#include "pycore_bytesobject.h" // _PyBytesWriter
|
||||
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
|
||||
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
|
||||
#include "pycore_long.h" // _PyLong_AsByteArray()
|
||||
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
||||
#include "pycore_object.h" // _PyNone_Type
|
||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||
#include "pycore_runtime.h" // _Py_ID()
|
||||
#include "pycore_setobject.h" // _PySet_NextEntry()
|
||||
#include "pycore_sysmodule.h" // _PySys_GetAttr()
|
||||
|
||||
#include <stdlib.h> // strtol()
|
||||
|
||||
|
@ -3413,15 +3414,21 @@ save_set(PickleState *state, PicklerObject *self, PyObject *obj)
|
|||
i = 0;
|
||||
if (_Pickler_Write(self, &mark_op, 1) < 0)
|
||||
return -1;
|
||||
while (_PySet_NextEntry(obj, &ppos, &item, &hash)) {
|
||||
Py_INCREF(item);
|
||||
int err = save(state, self, item, 0);
|
||||
|
||||
int err = 0;
|
||||
Py_BEGIN_CRITICAL_SECTION(obj);
|
||||
while (_PySet_NextEntryRef(obj, &ppos, &item, &hash)) {
|
||||
err = save(state, self, item, 0);
|
||||
Py_CLEAR(item);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
break;
|
||||
if (++i == BATCHSIZE)
|
||||
break;
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
if (err < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_Pickler_Write(self, &additems_op, 1) < 0)
|
||||
return -1;
|
||||
if (PySet_GET_SIZE(obj) != set_size) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "parts.h"
|
||||
#include "../_testcapi/util.h" // NULLABLE, RETURN_INT
|
||||
|
||||
#include "pycore_critical_section.h"
|
||||
#include "pycore_setobject.h"
|
||||
|
||||
|
||||
|
@ -27,10 +28,13 @@ set_next_entry(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
NULLABLE(set);
|
||||
|
||||
rc = _PySet_NextEntry(set, &pos, &item, &hash);
|
||||
Py_BEGIN_CRITICAL_SECTION(set);
|
||||
rc = _PySet_NextEntryRef(set, &pos, &item, &hash);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
if (rc == 1) {
|
||||
return Py_BuildValue("innO", rc, pos, hash, item);
|
||||
PyObject *ret = Py_BuildValue("innO", rc, pos, hash, item);
|
||||
Py_DECREF(item);
|
||||
return ret;
|
||||
}
|
||||
assert(item == UNINITIALIZED_PTR);
|
||||
assert(hash == (Py_hash_t)UNINITIALIZED_SIZE);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue