https://github.com/python/cpython/commit/ae132edc296d27c6ed04fe4d400c67e3cfb622e8
commit: ae132edc296d27c6ed04fe4d400c67e3cfb622e8
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2025-02-07T12:59:52+03:00
summary:

gh-129766: Fix crash on calling `warnings._release_lock` with no lock (#129771)

files:
A Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst
M Lib/test/test_warnings/__init__.py
M Python/_warnings.c

diff --git a/Lib/test/test_warnings/__init__.py 
b/Lib/test/test_warnings/__init__.py
index 4bd164b8a9a82b..6f4c569d247601 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -1432,6 +1432,17 @@ class 
PyEnvironmentVariableTests(EnvironmentVariableTests, unittest.TestCase):
     module = py_warnings
 
 
+class LocksTest(unittest.TestCase):
+    @support.cpython_only
+    @unittest.skipUnless(c_warnings, 'C module is required')
+    def test_release_lock_no_lock(self):
+        with self.assertRaisesRegex(
+            RuntimeError,
+            'cannot release un-acquired lock',
+        ):
+            c_warnings._release_lock()
+
+
 class _DeprecatedTest(BaseTest, unittest.TestCase):
 
     """Test _deprecated()."""
diff --git 
a/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst 
b/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst
new file mode 100644
index 00000000000000..76e908300a858d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst
@@ -0,0 +1,2 @@
+Fix crash in :mod:`warnings`, when calling ``_release_lock()`` with no
+existing lock.
diff --git a/Python/_warnings.c b/Python/_warnings.c
index bb195da9512caf..891db2743a28fc 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -240,12 +240,12 @@ warnings_lock(PyInterpreterState *interp)
     _PyRecursiveMutex_Lock(&st->lock);
 }
 
-static inline void
+static inline int
 warnings_unlock(PyInterpreterState *interp)
 {
     WarningsState *st = warnings_get_state(interp);
     assert(st != NULL);
-    _PyRecursiveMutex_Unlock(&st->lock);
+    return _PyRecursiveMutex_TryUnlock(&st->lock);
 }
 
 static inline bool
@@ -284,7 +284,10 @@ warnings_release_lock_impl(PyObject *module)
     if (interp == NULL) {
         return NULL;
     }
-    warnings_unlock(interp);
+    if (warnings_unlock(interp) < 0) {
+        PyErr_SetString(PyExc_RuntimeError, "cannot release un-acquired lock");
+        return NULL;
+    }
     Py_RETURN_NONE;
 }
 

_______________________________________________
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