Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-116664: Make module state Py_SETREF's in _warnings thread-safe #116959

Merged
merged 13 commits into from Mar 28, 2024
28 changes: 18 additions & 10 deletions Python/_warnings.c
@@ -1,4 +1,5 @@
#include "Python.h"
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_interp.h" // PyInterpreterState.warnings
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
Expand Down Expand Up @@ -235,14 +236,14 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
static PyObject *
get_once_registry(PyInterpreterState *interp)
{
PyObject *registry;
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(interp);

WarningsState *st = warnings_get_state(interp);
if (st == NULL) {
return NULL;
}

registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
PyObject *registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
if (registry == NULL) {
if (PyErr_Occurred())
return NULL;
Expand All @@ -265,14 +266,14 @@ get_once_registry(PyInterpreterState *interp)
static PyObject *
get_default_action(PyInterpreterState *interp)
{
PyObject *default_action;
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(interp);

WarningsState *st = warnings_get_state(interp);
if (st == NULL) {
return NULL;
}

default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
PyObject *default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
if (default_action == NULL) {
if (PyErr_Occurred()) {
return NULL;
Expand All @@ -299,15 +300,14 @@ get_filter(PyInterpreterState *interp, PyObject *category,
PyObject *text, Py_ssize_t lineno,
PyObject *module, PyObject **item)
{
PyObject *action;
Py_ssize_t i;
PyObject *warnings_filters;
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(interp);

WarningsState *st = warnings_get_state(interp);
if (st == NULL) {
return NULL;
}

warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
if (warnings_filters == NULL) {
if (PyErr_Occurred())
return NULL;
Expand All @@ -324,7 +324,7 @@ get_filter(PyInterpreterState *interp, PyObject *category,
}

/* WarningsState.filters could change while we are iterating over it. */
for (i = 0; i < PyList_GET_SIZE(filters); i++) {
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
Py_ssize_t ln;
int is_subclass, good_msg, good_mod;
Expand Down Expand Up @@ -384,7 +384,7 @@ get_filter(PyInterpreterState *interp, PyObject *category,
Py_DECREF(tmp_item);
}

action = get_default_action(interp);
PyObject *action = get_default_action(interp);
if (action != NULL) {
*item = Py_NewRef(Py_None);
return action;
Expand Down Expand Up @@ -1000,8 +1000,10 @@ do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
&filename, &lineno, &module, &registry))
return NULL;

Py_BEGIN_CRITICAL_SECTION(tstate->interp);
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
NULL, source);
Py_END_CRITICAL_SECTION();
Py_DECREF(filename);
Py_DECREF(registry);
Py_DECREF(module);
Expand Down Expand Up @@ -1149,8 +1151,10 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message,
return NULL;
}
}
Py_BEGIN_CRITICAL_SECTION(tstate->interp);
returned = warn_explicit(tstate, category, message, filename, lineno,
mod, registry, source_line, sourceobj);
Py_END_CRITICAL_SECTION();
Py_XDECREF(source_line);
return returned;
}
Expand Down Expand Up @@ -1290,8 +1294,10 @@ PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
if (tstate == NULL) {
return -1;
}
Py_BEGIN_CRITICAL_SECTION(tstate->interp);
res = warn_explicit(tstate, category, message, filename, lineno,
module, registry, NULL, NULL);
Py_END_CRITICAL_SECTION();
if (res == NULL)
return -1;
Py_DECREF(res);
Expand Down Expand Up @@ -1356,8 +1362,10 @@ PyErr_WarnExplicitFormat(PyObject *category,
PyObject *res;
PyThreadState *tstate = get_current_tstate();
if (tstate != NULL) {
Py_BEGIN_CRITICAL_SECTION(tstate->interp);
res = warn_explicit(tstate, category, message, filename, lineno,
module, registry, NULL, NULL);
Py_END_CRITICAL_SECTION();
Py_DECREF(message);
if (res != NULL) {
Py_DECREF(res);
Expand Down