@@ -3035,6 +3035,30 @@ fatal_error_exit(int status)
30353035 }
30363036}
30373037
3038+ static inline int
3039+ acquire_dict_lock_for_dump (PyObject * obj )
3040+ {
3041+ #ifdef Py_GIL_DISABLED
3042+ PyMutex * mutex = & obj -> ob_mutex ;
3043+ if (_PyMutex_LockTimed (mutex , 0 , 0 ) == PY_LOCK_ACQUIRED ) {
3044+ return 1 ;
3045+ }
3046+ return 0 ;
3047+ #else
3048+ return 1 ;
3049+ #endif
3050+ }
3051+
3052+ static inline void
3053+ release_dict_lock_for_dump (PyObject * obj )
3054+ {
3055+ #ifdef Py_GIL_DISABLED
3056+ PyMutex * mutex = & obj -> ob_mutex ;
3057+ // We can not call PyMutex_Unlock because it's not async-signal-safe.
3058+ // So not to wake up other threads, we just use a simple atomic store in here.
3059+ _Py_atomic_store_uint8 (& mutex -> _bits , _Py_UNLOCKED );
3060+ #endif
3061+ }
30383062
30393063// Dump the list of extension modules of sys.modules, excluding stdlib modules
30403064// (sys.stdlib_module_names), into fd file descriptor.
@@ -3062,13 +3086,18 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
30623086 PyObject * stdlib_module_names = NULL ;
30633087 if (interp -> sysdict != NULL ) {
30643088 pos = 0 ;
3065- while (PyDict_Next (interp -> sysdict , & pos , & key , & value )) {
3089+ if (!acquire_dict_lock_for_dump (interp -> sysdict )) {
3090+ // If we cannot acquire the lock, just don't dump the list of extension modules.
3091+ return ;
3092+ }
3093+ while (_PyDict_Next (interp -> sysdict , & pos , & key , & value , NULL )) {
30663094 if (PyUnicode_Check (key )
30673095 && PyUnicode_CompareWithASCIIString (key , "stdlib_module_names" ) == 0 ) {
30683096 stdlib_module_names = value ;
30693097 break ;
30703098 }
30713099 }
3100+ release_dict_lock_for_dump (interp -> sysdict );
30723101 }
30733102 // If we failed to get sys.stdlib_module_names or it's not a frozenset,
30743103 // don't exclude stdlib modules.
@@ -3080,7 +3109,11 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
30803109 int header = 1 ;
30813110 Py_ssize_t count = 0 ;
30823111 pos = 0 ;
3083- while (PyDict_Next (modules , & pos , & key , & value )) {
3112+ if (!acquire_dict_lock_for_dump (modules )) {
3113+ // If we cannot acquire the lock, just don't dump the list of extension modules.
3114+ return ;
3115+ }
3116+ while (_PyDict_Next (modules , & pos , & key , & value , NULL )) {
30843117 if (!PyUnicode_Check (key )) {
30853118 continue ;
30863119 }
@@ -3121,6 +3154,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
31213154 _Py_DumpASCII (fd , key );
31223155 count ++ ;
31233156 }
3157+ release_dict_lock_for_dump (modules );
31243158
31253159 if (count ) {
31263160 PUTS (fd , " (total: " );
0 commit comments