mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +00:00
[3.12] gh-124785: Revert "[3.12] gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)" (#124814)
Revert "[3.12] gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)"
This reverts commit 5dd07ebc0c
.
This commit is contained in:
parent
003771709b
commit
ffc6a10149
2 changed files with 6 additions and 47 deletions
|
@ -286,37 +286,13 @@ hashtable_unicode_compare(const void *key1, const void *key2)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return true if this interpreter should share the main interpreter's
|
||||
intern_dict. That's important for interpreters which load basic
|
||||
single-phase init extension modules (m_size == -1). There could be interned
|
||||
immortal strings that are shared between interpreters, due to the
|
||||
PyDict_Update(mdict, m_copy) call in import_find_extension().
|
||||
|
||||
It's not safe to deallocate those strings until all interpreters that
|
||||
potentially use them are freed. By storing them in the main interpreter, we
|
||||
ensure they get freed after all other interpreters are freed.
|
||||
*/
|
||||
static bool
|
||||
has_shared_intern_dict(PyInterpreterState *interp)
|
||||
{
|
||||
PyInterpreterState *main_interp = _PyInterpreterState_Main();
|
||||
return interp != main_interp && interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC;
|
||||
}
|
||||
|
||||
static int
|
||||
init_interned_dict(PyInterpreterState *interp)
|
||||
{
|
||||
assert(get_interned_dict(interp) == NULL);
|
||||
PyObject *interned;
|
||||
if (has_shared_intern_dict(interp)) {
|
||||
interned = get_interned_dict(_PyInterpreterState_Main());
|
||||
Py_INCREF(interned);
|
||||
}
|
||||
else {
|
||||
interned = PyDict_New();
|
||||
if (interned == NULL) {
|
||||
return -1;
|
||||
}
|
||||
PyObject *interned = interned = PyDict_New();
|
||||
if (interned == NULL) {
|
||||
return -1;
|
||||
}
|
||||
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = interned;
|
||||
return 0;
|
||||
|
@ -327,10 +303,7 @@ clear_interned_dict(PyInterpreterState *interp)
|
|||
{
|
||||
PyObject *interned = get_interned_dict(interp);
|
||||
if (interned != NULL) {
|
||||
if (!has_shared_intern_dict(interp)) {
|
||||
// only clear if the dict belongs to this interpreter
|
||||
PyDict_Clear(interned);
|
||||
}
|
||||
PyDict_Clear(interned);
|
||||
Py_DECREF(interned);
|
||||
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = NULL;
|
||||
}
|
||||
|
@ -15163,13 +15136,6 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
|
|||
}
|
||||
assert(PyDict_CheckExact(interned));
|
||||
|
||||
if (has_shared_intern_dict(interp)) {
|
||||
// the dict doesn't belong to this interpreter, skip the debug
|
||||
// checks on it and just clear the pointer to it
|
||||
clear_interned_dict(interp);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef INTERNED_STATS
|
||||
fprintf(stderr, "releasing %zd interned strings\n",
|
||||
PyDict_GET_SIZE(interned));
|
||||
|
@ -15688,10 +15654,8 @@ _PyUnicode_Fini(PyInterpreterState *interp)
|
|||
{
|
||||
struct _Py_unicode_state *state = &interp->unicode;
|
||||
|
||||
if (!has_shared_intern_dict(interp)) {
|
||||
// _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
|
||||
assert(get_interned_dict(interp) == NULL);
|
||||
}
|
||||
// _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
|
||||
assert(get_interned_dict(interp) == NULL);
|
||||
|
||||
_PyUnicode_FiniEncodings(&state->fs_codec);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue