@@ -277,13 +277,37 @@ hashtable_unicode_compare(const void *key1, const void *key2)
277277 }
278278}
279279
280+ /* Return true if this interpreter should share the main interpreter's
281+ intern_dict. That's important for interpreters which load basic
282+ single-phase init extension modules (m_size == -1). There could be interned
283+ immortal strings that are shared between interpreters, due to the
284+ PyDict_Update(mdict, m_copy) call in import_find_extension().
285+
286+ It's not safe to deallocate those strings until all interpreters that
287+ potentially use them are freed. By storing them in the main interpreter, we
288+ ensure they get freed after all other interpreters are freed.
289+ */
290+ static bool
291+ has_shared_intern_dict (PyInterpreterState * interp )
292+ {
293+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
294+ return interp != main_interp && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ;
295+ }
296+
280297static int
281298init_interned_dict (PyInterpreterState * interp )
282299{
283300 assert (get_interned_dict (interp ) == NULL );
284- PyObject * interned = interned = PyDict_New ();
285- if (interned == NULL ) {
286- return -1 ;
301+ PyObject * interned ;
302+ if (has_shared_intern_dict (interp )) {
303+ interned = get_interned_dict (_PyInterpreterState_Main ());
304+ Py_INCREF (interned );
305+ }
306+ else {
307+ interned = PyDict_New ();
308+ if (interned == NULL ) {
309+ return -1 ;
310+ }
287311 }
288312 _Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = interned ;
289313 return 0 ;
@@ -294,7 +318,10 @@ clear_interned_dict(PyInterpreterState *interp)
294318{
295319 PyObject * interned = get_interned_dict (interp );
296320 if (interned != NULL ) {
297- PyDict_Clear (interned );
321+ if (!has_shared_intern_dict (interp )) {
322+ // only clear if the dict belongs to this interpreter
323+ PyDict_Clear (interned );
324+ }
298325 Py_DECREF (interned );
299326 _Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = NULL ;
300327 }
@@ -15306,6 +15333,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1530615333 }
1530715334 assert (PyDict_CheckExact (interned ));
1530815335
15336+ if (has_shared_intern_dict (interp )) {
15337+ // the dict doesn't belong to this interpreter, skip the debug
15338+ // checks on it and just clear the pointer to it
15339+ clear_interned_dict (interp );
15340+ return ;
15341+ }
15342+
1530915343#ifdef INTERNED_STATS
1531015344 fprintf (stderr , "releasing %zd interned strings\n" ,
1531115345 PyDict_GET_SIZE (interned ));
@@ -15827,8 +15861,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
1582715861{
1582815862 struct _Py_unicode_state * state = & interp -> unicode ;
1582915863
15830- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15831- assert (get_interned_dict (interp ) == NULL );
15864+ if (!has_shared_intern_dict (interp )) {
15865+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15866+ assert (get_interned_dict (interp ) == NULL );
15867+ }
1583215868
1583315869 _PyUnicode_FiniEncodings (& state -> fs_codec );
1583415870
0 commit comments