mirror of https://github.com/python/cpython
[3.13] gh-120837: Update _Py_DumpExtensionModules to be async-signal-safe (gh-121051) (gh-121107)
gh-120837: Update _Py_DumpExtensionModules to be async-signal-safe (gh-121051)
(cherry picked from commit 1a2e7a7475
)
Co-authored-by: Donghee Na <donghee.na@python.org>
This commit is contained in:
parent
49a01d6290
commit
d5441f6aac
|
@ -3036,6 +3036,30 @@ fatal_error_exit(int status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
acquire_dict_lock_for_dump(PyObject *obj)
|
||||||
|
{
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMutex *mutex = &obj->ob_mutex;
|
||||||
|
if (_PyMutex_LockTimed(mutex, 0, 0) == PY_LOCK_ACQUIRED) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
release_dict_lock_for_dump(PyObject *obj)
|
||||||
|
{
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMutex *mutex = &obj->ob_mutex;
|
||||||
|
// We can not call PyMutex_Unlock because it's not async-signal-safe.
|
||||||
|
// So not to wake up other threads, we just use a simple atomic store in here.
|
||||||
|
_Py_atomic_store_uint8(&mutex->_bits, _Py_UNLOCKED);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Dump the list of extension modules of sys.modules, excluding stdlib modules
|
// Dump the list of extension modules of sys.modules, excluding stdlib modules
|
||||||
// (sys.stdlib_module_names), into fd file descriptor.
|
// (sys.stdlib_module_names), into fd file descriptor.
|
||||||
|
@ -3063,13 +3087,18 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
|
||||||
PyObject *stdlib_module_names = NULL;
|
PyObject *stdlib_module_names = NULL;
|
||||||
if (interp->sysdict != NULL) {
|
if (interp->sysdict != NULL) {
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (PyDict_Next(interp->sysdict, &pos, &key, &value)) {
|
if (!acquire_dict_lock_for_dump(interp->sysdict)) {
|
||||||
|
// If we cannot acquire the lock, just don't dump the list of extension modules.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (_PyDict_Next(interp->sysdict, &pos, &key, &value, NULL)) {
|
||||||
if (PyUnicode_Check(key)
|
if (PyUnicode_Check(key)
|
||||||
&& PyUnicode_CompareWithASCIIString(key, "stdlib_module_names") == 0) {
|
&& PyUnicode_CompareWithASCIIString(key, "stdlib_module_names") == 0) {
|
||||||
stdlib_module_names = value;
|
stdlib_module_names = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
release_dict_lock_for_dump(interp->sysdict);
|
||||||
}
|
}
|
||||||
// If we failed to get sys.stdlib_module_names or it's not a frozenset,
|
// If we failed to get sys.stdlib_module_names or it's not a frozenset,
|
||||||
// don't exclude stdlib modules.
|
// don't exclude stdlib modules.
|
||||||
|
@ -3081,7 +3110,11 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
|
||||||
int header = 1;
|
int header = 1;
|
||||||
Py_ssize_t count = 0;
|
Py_ssize_t count = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (PyDict_Next(modules, &pos, &key, &value)) {
|
if (!acquire_dict_lock_for_dump(modules)) {
|
||||||
|
// If we cannot acquire the lock, just don't dump the list of extension modules.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (_PyDict_Next(modules, &pos, &key, &value, NULL)) {
|
||||||
if (!PyUnicode_Check(key)) {
|
if (!PyUnicode_Check(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -3122,6 +3155,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
|
||||||
_Py_DumpASCII(fd, key);
|
_Py_DumpASCII(fd, key);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
release_dict_lock_for_dump(modules);
|
||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
PUTS(fd, " (total: ");
|
PUTS(fd, " (total: ");
|
||||||
|
|
Loading…
Reference in New Issue