Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5dd07eb

Browse files
authored
[3.12]gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)
Fix a crash caused by immortal interned strings being shared betweensub-interpreters that use basic single-phase init. In that case, the stringcan be used by an interpreter that outlives the interpreter that created andinterned it. For interpreters that share obmalloc state, also share theinterned dict with the main interpreter.
1 parent69fd1f2 commit5dd07eb

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix a crash caused by immortal interned strings being shared between
2+
sub-interpreters that use basic single-phase init. In that case, the string
3+
can be used by an interpreter that outlives the interpeter that created and
4+
interned it. For interpreters that share obmalloc state, also share the
5+
interned dict with the main interpreter.

‎Objects/unicodeobject.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,23 @@ hashtable_unicode_compare(const void *key1, const void *key2)
266266
}
267267
}
268268

269+
/* Return true if this interpreter should share the main interpreter's
270+
intern_dict. That's important for interpreters which load basic
271+
single-phase init extension modules (m_size == -1). There could be interned
272+
immortal strings that are shared between interpreters, due to the
273+
PyDict_Update(mdict, m_copy) call in import_find_extension().
274+
275+
It's not safe to deallocate those strings until all interpreters that
276+
potentially use them are freed. By storing them in the main interpreter, we
277+
ensure they get freed after all other interpreters are freed.
278+
*/
279+
staticbool
280+
has_shared_intern_dict(PyInterpreterState*interp)
281+
{
282+
PyInterpreterState*main_interp=_PyInterpreterState_Main();
283+
returninterp!=main_interp&&interp->feature_flags&Py_RTFLAGS_USE_MAIN_OBMALLOC;
284+
}
285+
269286
staticint
270287
init_interned_dict(PyInterpreterState*interp)
271288
{
@@ -284,9 +301,16 @@ init_interned_dict(PyInterpreterState *interp)
284301
}
285302
}
286303
assert(get_interned_dict(interp)==NULL);
287-
PyObject*interned=interned=PyDict_New();
288-
if (interned==NULL) {
289-
return-1;
304+
PyObject*interned;
305+
if (has_shared_intern_dict(interp)) {
306+
interned=get_interned_dict(_PyInterpreterState_Main());
307+
Py_INCREF(interned);
308+
}
309+
else {
310+
interned=PyDict_New();
311+
if (interned==NULL) {
312+
return-1;
313+
}
290314
}
291315
_Py_INTERP_CACHED_OBJECT(interp,interned_strings)=interned;
292316
return0;
@@ -297,7 +321,10 @@ clear_interned_dict(PyInterpreterState *interp)
297321
{
298322
PyObject*interned=get_interned_dict(interp);
299323
if (interned!=NULL) {
300-
PyDict_Clear(interned);
324+
if (!has_shared_intern_dict(interp)) {
325+
// only clear if the dict belongs to this interpreter
326+
PyDict_Clear(interned);
327+
}
301328
Py_DECREF(interned);
302329
_Py_INTERP_CACHED_OBJECT(interp,interned_strings)=NULL;
303330
}
@@ -14861,6 +14888,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1486114888
}
1486214889
assert(PyDict_CheckExact(interned));
1486314890

14891+
if (has_shared_intern_dict(interp)) {
14892+
// the dict doesn't belong to this interpreter, skip the debug
14893+
// checks on it and just clear the pointer to it
14894+
clear_interned_dict(interp);
14895+
return;
14896+
}
14897+
1486414898
/* TODO:
1486514899
* Currently, the runtime is not able to guarantee that it can exit without
1486614900
* allocations that carry over to a future initialization of Python within
@@ -15364,8 +15398,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
1536415398
{
1536515399
struct_Py_unicode_state*state=&interp->unicode;
1536615400

15367-
// _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15368-
assert(get_interned_dict(interp)==NULL);
15401+
if (!has_shared_intern_dict(interp)) {
15402+
// _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15403+
assert(get_interned_dict(interp)==NULL);
15404+
}
1536915405

1537015406
_PyUnicode_FiniEncodings(&state->fs_codec);
1537115407

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp