@@ -287,13 +287,37 @@ hashtable_unicode_compare(const void *key1, const void *key2)
287
287
}
288
288
}
289
289
290
+ /* Return true if this interpreter should share the main interpreter's
291
+ intern_dict. That's important for interpreters which load basic
292
+ single-phase init extension modules (m_size == -1). There could be interned
293
+ immortal strings that are shared between interpreters, due to the
294
+ PyDict_Update(mdict, m_copy) call in import_find_extension().
295
+
296
+ It's not safe to deallocate those strings until all interpreters that
297
+ potentially use them are freed. By storing them in the main interpreter, we
298
+ ensure they get freed after all other interpreters are freed.
299
+ */
300
+ static bool
301
+ has_shared_intern_dict (PyInterpreterState * interp )
302
+ {
303
+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
304
+ return interp != main_interp && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ;
305
+ }
306
+
290
307
static int
291
308
init_interned_dict (PyInterpreterState * interp )
292
309
{
293
310
assert (get_interned_dict (interp ) == NULL );
294
- PyObject * interned = interned = PyDict_New ();
295
- if (interned == NULL ) {
296
- return -1 ;
311
+ PyObject * interned ;
312
+ if (has_shared_intern_dict (interp )) {
313
+ interned = get_interned_dict (_PyInterpreterState_Main ());
314
+ Py_INCREF (interned );
315
+ }
316
+ else {
317
+ interned = PyDict_New ();
318
+ if (interned == NULL ) {
319
+ return -1 ;
320
+ }
297
321
}
298
322
_Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = interned ;
299
323
return 0 ;
@@ -304,7 +328,10 @@ clear_interned_dict(PyInterpreterState *interp)
304
328
{
305
329
PyObject * interned = get_interned_dict (interp );
306
330
if (interned != NULL ) {
307
- PyDict_Clear (interned );
331
+ if (!has_shared_intern_dict (interp )) {
332
+ // only clear if the dict belongs to this interpreter
333
+ PyDict_Clear (interned );
334
+ }
308
335
Py_DECREF (interned );
309
336
_Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = NULL ;
310
337
}
@@ -14939,6 +14966,10 @@ _PyUnicode_InternStatic(PyInterpreterState *interp, PyObject **p)
14939
14966
assert (* p );
14940
14967
}
14941
14968
14969
+ #ifdef Py_TRACE_REFS
14970
+ extern void _Py_NormalizeImmortalReference (PyObject * );
14971
+ #endif
14972
+
14942
14973
static void
14943
14974
immortalize_interned (PyObject * s )
14944
14975
{
@@ -14954,6 +14985,10 @@ immortalize_interned(PyObject *s)
14954
14985
#endif
14955
14986
_PyUnicode_STATE (s ).interned = SSTATE_INTERNED_IMMORTAL ;
14956
14987
_Py_SetImmortal (s );
14988
+ #ifdef Py_TRACE_REFS
14989
+ /* Make sure the ref is associated with the right interpreter. */
14990
+ _Py_NormalizeImmortalReference (s );
14991
+ #endif
14957
14992
}
14958
14993
14959
14994
static /* non-null */ PyObject *
@@ -15140,6 +15175,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
15140
15175
}
15141
15176
assert (PyDict_CheckExact (interned ));
15142
15177
15178
+ if (has_shared_intern_dict (interp )) {
15179
+ // the dict doesn't belong to this interpreter, skip the debug
15180
+ // checks on it and just clear the pointer to it
15181
+ clear_interned_dict (interp );
15182
+ return ;
15183
+ }
15184
+
15143
15185
#ifdef INTERNED_STATS
15144
15186
fprintf (stderr , "releasing %zd interned strings\n" ,
15145
15187
PyDict_GET_SIZE (interned ));
@@ -15658,8 +15700,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
15658
15700
{
15659
15701
struct _Py_unicode_state * state = & interp -> unicode ;
15660
15702
15661
- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15662
- assert (get_interned_dict (interp ) == NULL );
15703
+ if (!has_shared_intern_dict (interp )) {
15704
+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15705
+ assert (get_interned_dict (interp ) == NULL );
15706
+ }
15663
15707
15664
15708
_PyUnicode_FiniEncodings (& state -> fs_codec );
15665
15709
0 commit comments