https://github.com/python/cpython/commit/d5441f6aacc1eab69ad539445568a2ef779cb267
commit: d5441f6aacc1eab69ad539445568a2ef779cb267
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: corona10 <[email protected]>
date: 2024-06-27T22:12:12Z
summary:

[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 1a2e7a747540f74414e7c50556bcb2cc127e9d1c)

Co-authored-by: Donghee Na <[email protected]>

files:
M Python/pylifecycle.c

diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index af9d4edde1525a..13bd62da4d0484 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -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.
@@ -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.
@@ -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;
         }
@@ -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: ");

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to