@@ -282,13 +282,37 @@ hashtable_unicode_compare(const void *key1, const void *key2)
282282 }
283283}
284284
285+ /* Return true if this interpreter should share the main interpreter's
286+ intern_dict. That's important for interpreters which load basic
287+ single-phase init extension modules (m_size == -1). There could be interned
288+ immortal strings that are shared between interpreters, due to the
289+ PyDict_Update(mdict, m_copy) call in import_find_extension().
290+
291+ It's not safe to deallocate those strings until all interpreters that
292+ potentially use them are freed. By storing them in the main interpreter, we
293+ ensure they get freed after all other interpreters are freed.
294+ */
295+ static bool
296+ has_shared_intern_dict (PyInterpreterState * interp )
297+ {
298+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
299+ return interp != main_interp && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ;
300+ }
301+
285302static int
286303init_interned_dict (PyInterpreterState * interp )
287304{
288305 assert (get_interned_dict (interp ) == NULL );
289- PyObject * interned = interned = PyDict_New ();
290- if (interned == NULL ) {
291- return -1 ;
306+ PyObject * interned ;
307+ if (has_shared_intern_dict (interp )) {
308+ interned = get_interned_dict (_PyInterpreterState_Main ());
309+ Py_INCREF (interned );
310+ }
311+ else {
312+ interned = PyDict_New ();
313+ if (interned == NULL ) {
314+ return -1 ;
315+ }
292316 }
293317 _Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = interned ;
294318 return 0 ;
@@ -299,7 +323,10 @@ clear_interned_dict(PyInterpreterState *interp)
299323{
300324 PyObject * interned = get_interned_dict (interp );
301325 if (interned != NULL ) {
302- PyDict_Clear (interned );
326+ if (!has_shared_intern_dict (interp )) {
327+ // only clear if the dict belongs to this interpreter
328+ PyDict_Clear (interned );
329+ }
303330 Py_DECREF (interned );
304331 _Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = NULL ;
305332 }
@@ -15618,6 +15645,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1561815645 }
1561915646 assert (PyDict_CheckExact (interned ));
1562015647
15648+ if (has_shared_intern_dict (interp )) {
15649+ // the dict doesn't belong to this interpreter, skip the debug
15650+ // checks on it and just clear the pointer to it
15651+ clear_interned_dict (interp );
15652+ return ;
15653+ }
15654+
1562115655#ifdef INTERNED_STATS
1562215656 fprintf (stderr , "releasing %zd interned strings\n" ,
1562315657 PyDict_GET_SIZE (interned ));
@@ -16126,8 +16160,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
1612616160{
1612716161 struct _Py_unicode_state * state = & interp -> unicode ;
1612816162
16129- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
16130- assert (get_interned_dict (interp ) == NULL );
16163+ if (!has_shared_intern_dict (interp )) {
16164+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
16165+ assert (get_interned_dict (interp ) == NULL );
16166+ }
1613116167
1613216168 _PyUnicode_FiniEncodings (& state -> fs_codec );
1613316169
0 commit comments