bpo-39796: Fix _warnings module initialization (GH-18739)

* Add _PyWarnings_InitState() which only initializes the _warnings
  module state (tstate->interp->warnings) without creating a module
  object
* Py_InitializeFromConfig() now calls _PyWarnings_InitState() instead
  of _PyWarnings_Init()
* Rename also private functions of _warnings.c to avoid confusion
  between the public C API and the private C API.
This commit is contained in:
Victor Stinner 2020-03-02 15:02:18 +01:00 committed by GitHub
parent 4482337dec
commit 66b7973c1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 15 deletions

View File

@ -17,6 +17,8 @@ struct _warnings_runtime_state {
long filters_version;
};
extern PyStatus _PyWarnings_InitState(PyThreadState *tstate);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,5 @@
#include "Python.h"
#include "pycore_initconfig.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h"
#include "frameobject.h"
@ -28,12 +29,12 @@ _Py_IDENTIFIER(__name__);
/* Given a module object, get its per-module state. */
static WarningsState *
_Warnings_GetState()
warnings_get_state(void)
{
PyThreadState *tstate = _PyThreadState_GET();
if (tstate == NULL) {
_PyErr_SetString(tstate, PyExc_RuntimeError,
"_Warnings_GetState: could not identify "
"warnings_get_state: could not identify "
"current interpreter");
return NULL;
}
@ -42,7 +43,7 @@ _Warnings_GetState()
/* Clear the given warnings module state. */
static void
_Warnings_ClearState(WarningsState *st)
warnings_clear_state(WarningsState *st)
{
Py_CLEAR(st->filters);
Py_CLEAR(st->once_registry);
@ -112,7 +113,7 @@ init_filters(void)
/* Initialize the given warnings module state. */
static int
_Warnings_InitState(WarningsState *st)
warnings_init_state(WarningsState *st)
{
if (st->filters == NULL) {
st->filters = init_filters();
@ -140,7 +141,7 @@ _Warnings_InitState(WarningsState *st)
return 0;
error:
_Warnings_ClearState(st);
warnings_clear_state(st);
return -1;
}
@ -286,7 +287,7 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
Py_ssize_t i;
PyObject *warnings_filters;
_Py_IDENTIFIER(filters);
WarningsState *st = _Warnings_GetState();
WarningsState *st = warnings_get_state();
if (st == NULL) {
return NULL;
}
@ -388,7 +389,7 @@ already_warned(PyObject *registry, PyObject *key, int should_set)
if (key == NULL)
return -1;
WarningsState *st = _Warnings_GetState();
WarningsState *st = warnings_get_state();
if (st == NULL) {
return -1;
}
@ -706,7 +707,7 @@ warn_explicit(PyObject *category, PyObject *message,
if (_PyUnicode_EqualToASCIIString(action, "once")) {
if (registry == NULL || registry == Py_None) {
WarningsState *st = _Warnings_GetState();
WarningsState *st = warnings_get_state();
if (st == NULL) {
goto cleanup;
}
@ -1066,7 +1067,7 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject *
warnings_filters_mutated(PyObject *self, PyObject *args)
{
WarningsState *st = _Warnings_GetState();
WarningsState *st = warnings_get_state();
if (st == NULL) {
return NULL;
}
@ -1333,6 +1334,16 @@ static struct PyModuleDef warningsmodule = {
};
PyStatus
_PyWarnings_InitState(PyThreadState *tstate)
{
if (warnings_init_state(&tstate->interp->warnings) < 0) {
return _PyStatus_ERR("can't initialize warnings");
}
return _PyStatus_OK();
}
PyMODINIT_FUNC
_PyWarnings_Init(void)
{
@ -1343,11 +1354,11 @@ _PyWarnings_Init(void)
return NULL;
}
WarningsState *st = _Warnings_GetState();
WarningsState *st = warnings_get_state();
if (st == NULL) {
goto error;
}
if (_Warnings_InitState(st) < 0) {
if (warnings_init_state(st) < 0) {
goto error;
}
@ -1370,7 +1381,7 @@ _PyWarnings_Init(void)
error:
if (st != NULL) {
_Warnings_ClearState(st);
warnings_clear_state(st);
}
Py_DECREF(m);
return NULL;
@ -1380,5 +1391,5 @@ error:
void
_PyWarnings_Fini(PyInterpreterState *interp)
{
_Warnings_ClearState(&interp->warnings);
warnings_clear_state(&interp->warnings);
}

View File

@ -677,8 +677,9 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
const PyConfig *config = &tstate->interp->config;
if (_Py_IsMainInterpreter(tstate)) {
/* Initialize _warnings. */
if (_PyWarnings_Init() == NULL) {
return _PyStatus_ERR("can't initialize warnings");
status = _PyWarnings_InitState(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
if (config->_install_importlib) {