Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use re-entrant lock for warnings module.
  • Loading branch information
nascheme committed Jan 1, 2025
commit 152127603b0ba7012cb0bb7767a45d7b39b7ec39
2 changes: 1 addition & 1 deletion Include/internal/pycore_warnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct _warnings_runtime_state {
PyObject *filters; /* List */
PyObject *once_registry; /* Dict */
PyObject *default_action; /* String */
PyMutex mutex;
_PyRecursiveMutex lock;
long filters_version;
};

Expand Down
5 changes: 1 addition & 4 deletions Lib/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -905,10 +905,7 @@ def __exit__(self, *args):

import _thread

# Note that this is a non-reentrant lock, matching what's used by
# _acquire_lock() and _release_lock(). Care must be taken to
# not deadlock.
_lock = _thread.LockType()
_lock = _thread.RLock()

_filters_version = 1

Expand Down
32 changes: 16 additions & 16 deletions Python/_warnings.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ warnings_acquire_lock_impl(PyObject *module)
WarningsState *st = warnings_get_state(interp);
assert(st != NULL);

_PyMutex_Lock(&st->mutex);
_PyRecursiveMutex_Lock(&st->lock);
Py_RETURN_NONE;
}

Expand All @@ -270,7 +270,7 @@ warnings_release_lock_impl(PyObject *module)
WarningsState *st = warnings_get_state(interp);
assert(st != NULL);

_PyMutex_Unlock(&st->mutex);
_PyRecursiveMutex_Unlock(&st->lock);
Py_RETURN_NONE;
}

Expand All @@ -280,7 +280,7 @@ get_once_registry(PyInterpreterState *interp)
WarningsState *st = warnings_get_state(interp);
assert(st != NULL);

_Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
assert(PyMutex_IsLocked(&st->lock.mutex));

PyObject *registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
if (registry == NULL) {
Expand Down Expand Up @@ -308,7 +308,7 @@ get_default_action(PyInterpreterState *interp)
WarningsState *st = warnings_get_state(interp);
assert(st != NULL);

_Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
assert(PyMutex_IsLocked(&st->lock.mutex));

PyObject *default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
if (default_action == NULL) {
Expand Down Expand Up @@ -340,7 +340,7 @@ get_filter(PyInterpreterState *interp, PyObject *category,
WarningsState *st = warnings_get_state(interp);
assert(st != NULL);

_Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
assert(PyMutex_IsLocked(&st->lock.mutex));

PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
if (warnings_filters == NULL) {
Expand Down Expand Up @@ -440,7 +440,7 @@ already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,

WarningsState *st = warnings_get_state(interp);
assert(st != NULL);
_Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
assert(PyMutex_IsLocked(&st->lock.mutex));

PyObject *version_obj;
if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
Expand Down Expand Up @@ -1040,10 +1040,10 @@ do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
assert(st != NULL);
#endif

Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
_PyRecursiveMutex_Lock(&st->lock);
res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
NULL, source);
Py_END_CRITICAL_SECTION();
_PyRecursiveMutex_Unlock(&st->lock);
Py_DECREF(filename);
Py_DECREF(registry);
Py_DECREF(module);
Expand Down Expand Up @@ -1197,10 +1197,10 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message,
assert(st != NULL);
#endif

Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
_PyRecursiveMutex_Lock(&st->lock);
returned = warn_explicit(tstate, category, message, filename, lineno,
mod, registry, source_line, sourceobj);
Py_END_CRITICAL_SECTION();
_PyRecursiveMutex_Unlock(&st->lock);
Py_XDECREF(source_line);
return returned;
}
Expand All @@ -1223,8 +1223,8 @@ warnings_filters_mutated_lock_held_impl(PyObject *module)
assert(st != NULL);

// Note that the lock must be held by the caller.
if (!PyMutex_IsLocked(&st->mutex)) {
PyErr_SetString(PyExc_RuntimeError, "warnings mutex is not held");
if (!PyMutex_IsLocked(&st->lock.mutex)) {
PyErr_SetString(PyExc_RuntimeError, "warnings lock is not held");
return NULL;
}

Expand Down Expand Up @@ -1352,10 +1352,10 @@ PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
assert(st != NULL);
#endif

Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
_PyRecursiveMutex_Lock(&st->lock);
res = warn_explicit(tstate, category, message, filename, lineno,
module, registry, NULL, NULL);
Py_END_CRITICAL_SECTION();
_PyRecursiveMutex_Unlock(&st->lock);
if (res == NULL)
return -1;
Py_DECREF(res);
Expand Down Expand Up @@ -1425,10 +1425,10 @@ PyErr_WarnExplicitFormat(PyObject *category,
assert(st != NULL);
#endif

Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
_PyRecursiveMutex_Lock(&st->lock);
res = warn_explicit(tstate, category, message, filename, lineno,
module, registry, NULL, NULL);
Py_END_CRITICAL_SECTION();
_PyRecursiveMutex_Unlock(&st->lock);
Py_DECREF(message);
if (res != NULL) {
Py_DECREF(res);
Expand Down