@@ -3035,6 +3035,30 @@ fatal_error_exit(int status)
3035
3035
}
3036
3036
}
3037
3037
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
+ }
3038
3062
3039
3063
// Dump the list of extension modules of sys.modules, excluding stdlib modules
3040
3064
// (sys.stdlib_module_names), into fd file descriptor.
@@ -3062,13 +3086,18 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3062
3086
PyObject * stdlib_module_names = NULL ;
3063
3087
if (interp -> sysdict != NULL ) {
3064
3088
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 )) {
3066
3094
if (PyUnicode_Check (key )
3067
3095
&& PyUnicode_CompareWithASCIIString (key , "stdlib_module_names" ) == 0 ) {
3068
3096
stdlib_module_names = value ;
3069
3097
break ;
3070
3098
}
3071
3099
}
3100
+ release_dict_lock_for_dump (interp -> sysdict );
3072
3101
}
3073
3102
// If we failed to get sys.stdlib_module_names or it's not a frozenset,
3074
3103
// don't exclude stdlib modules.
@@ -3080,7 +3109,11 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3080
3109
int header = 1 ;
3081
3110
Py_ssize_t count = 0 ;
3082
3111
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 )) {
3084
3117
if (!PyUnicode_Check (key )) {
3085
3118
continue ;
3086
3119
}
@@ -3121,6 +3154,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
3121
3154
_Py_DumpASCII (fd , key );
3122
3155
count ++ ;
3123
3156
}
3157
+ release_dict_lock_for_dump (modules );
3124
3158
3125
3159
if (count ) {
3126
3160
PUTS (fd , " (total: " );
0 commit comments