Skip to content

Commit

Permalink
[3.13] gh-120837: Update _Py_DumpExtensionModules to be async-signal-…
Browse files Browse the repository at this point in the history
…safe (gh-121051) (gh-121107)

gh-120837: Update _Py_DumpExtensionModules to be async-signal-safe (gh-121051)
(cherry picked from commit 1a2e7a7)

Co-authored-by: Donghee Na <[email protected]>
  • Loading branch information
miss-islington and corona10 authored Jun 27, 2024
1 parent 49a01d6 commit d5441f6
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
// (sys.stdlib_module_names), into fd file descriptor.
Expand Down Expand Up @@ -3063,13 +3087,18 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
PyObject *stdlib_module_names = NULL;
if (interp->sysdict != NULL) {
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)
&& PyUnicode_CompareWithASCIIString(key, "stdlib_module_names") == 0) {
stdlib_module_names = value;
break;
}
}
release_dict_lock_for_dump(interp->sysdict);
}
// If we failed to get sys.stdlib_module_names or it's not a frozenset,
// don't exclude stdlib modules.
Expand All @@ -3081,7 +3110,11 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
int header = 1;
Py_ssize_t count = 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)) {
continue;
}
Expand Down Expand Up @@ -3122,6 +3155,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
_Py_DumpASCII(fd, key);
count++;
}
release_dict_lock_for_dump(modules);

if (count) {
PUTS(fd, " (total: ");
Expand Down

0 comments on commit d5441f6

Please sign in to comment.