]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129766: Fix crash on calling `warnings._release_lock` with no lock (#129771)
authorsobolevn <mail@sobolevn.me>
Fri, 7 Feb 2025 09:59:52 +0000 (12:59 +0300)
committerGitHub <noreply@github.com>
Fri, 7 Feb 2025 09:59:52 +0000 (12:59 +0300)
Lib/test/test_warnings/__init__.py
Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst [new file with mode: 0644]
Python/_warnings.c

index 4bd164b8a9a82b6b6e48349beb341d9edab2dae8..6f4c569d2476014c0c3fee449e2162646c227848 100644 (file)
@@ -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 (file)
index 0000000..76e9083
--- /dev/null
@@ -0,0 +1,2 @@
+Fix crash in :mod:`warnings`, when calling ``_release_lock()`` with no
+existing lock.
index bb195da9512caf9e377cdb9d55dbd27878ab8717..891db2743a28fc4e6ef52f044786b0ad535f4a03 100644 (file)
@@ -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;
 }