@@ -3036,6 +3036,30 @@ fatal_error_exit(int status)
3036
3036
}
3037
3037
}
3038
3038
3039
+ static inline int
3040
+ acquire_dict_lock_for_dump (PyObject * obj )
3041
+ {
3042
+ #ifdef Py_GIL_DISABLED
3043
+ PyMutex * mutex = & obj -> ob_mutex ;
3044
+ if (_PyMutex_LockTimed (mutex , 0 , 0 ) == PY_LOCK_ACQUIRED ) {
3045
+ return 1 ;
3046
+ }
3047
+ return 0 ;
3048
+ #else
3049
+ return 1 ;
3050
+ #endif
3051
+ }
3052
+
3053
+ static inline void
3054
+ release_dict_lock_for_dump (PyObject * obj )
3055
+ {
3056
+ #ifdef Py_GIL_DISABLED
3057
+ PyMutex * mutex = & obj -> ob_mutex ;
3058
+ // We can not call PyMutex_Unlock because it's not async-signal-safe.
3059
+ // So not to wake up other threads, we just use a simple atomic store in here.
3060
+ _Py_atomic_store_uint8 (& mutex -> _bits , _Py_UNLOCKED );
3061
+ #endif
3062
+ }
3039
3063
3040
3064
// Dump the list of extension modules of sys.modules, excluding stdlib modules
3041
3065
// (sys.stdlib_module_names), into fd file descriptor.
@@ -3063,13 +3087,18 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3063
3087
PyObject * stdlib_module_names = NULL ;
3064
3088
if (interp -> sysdict != NULL ) {
3065
3089
pos = 0 ;
3066
- while (PyDict_Next (interp -> sysdict , & pos , & key , & value )) {
3090
+ if (!acquire_dict_lock_for_dump (interp -> sysdict )) {
3091
+ // If we cannot acquire the lock, just don't dump the list of extension modules.
3092
+ return ;
3093
+ }
3094
+ while (_PyDict_Next (interp -> sysdict , & pos , & key , & value , NULL )) {
3067
3095
if (PyUnicode_Check (key )
3068
3096
&& PyUnicode_CompareWithASCIIString (key , "stdlib_module_names" ) == 0 ) {
3069
3097
stdlib_module_names = value ;
3070
3098
break ;
3071
3099
}
3072
3100
}
3101
+ release_dict_lock_for_dump (interp -> sysdict );
3073
3102
}
3074
3103
// If we failed to get sys.stdlib_module_names or it's not a frozenset,
3075
3104
// don't exclude stdlib modules.
@@ -3081,7 +3110,11 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3081
3110
int header = 1 ;
3082
3111
Py_ssize_t count = 0 ;
3083
3112
pos = 0 ;
3084
- while (PyDict_Next (modules , & pos , & key , & value )) {
3113
+ if (!acquire_dict_lock_for_dump (modules )) {
3114
+ // If we cannot acquire the lock, just don't dump the list of extension modules.
3115
+ return ;
3116
+ }
3117
+ while (_PyDict_Next (modules , & pos , & key , & value , NULL )) {
3085
3118
if (!PyUnicode_Check (key )) {
3086
3119
continue ;
3087
3120
}
@@ -3122,6 +3155,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3122
3155
_Py_DumpASCII (fd , key );
3123
3156
count ++ ;
3124
3157
}
3158
+ release_dict_lock_for_dump (modules );
3125
3159
3126
3160
if (count ) {
3127
3161
PUTS (fd , " (total: " );
0 commit comments