mirror of https://github.com/python/cpython
bpo-38644: Make tstate more explicit inside pystate.c (GH-19182)
Fix PyInterpreterState_New(): Don't call PyErr_SetString() when there is no current Python thread state (if tstate is NULL).
This commit is contained in:
parent
728189884e
commit
71a3522ef8
|
@ -1119,6 +1119,8 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
|
||||||
Return the interpreter's unique ID. If there was any error in doing
|
Return the interpreter's unique ID. If there was any error in doing
|
||||||
so then ``-1`` is returned and an error is set.
|
so then ``-1`` is returned and an error is set.
|
||||||
|
|
||||||
|
The caller must hold the GIL.
|
||||||
|
|
||||||
.. versionadded:: 3.7
|
.. versionadded:: 3.7
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,8 @@ since multiple such modules can be created from a single definition.
|
||||||
mechanisms (either by calling it directly, or by referring to its
|
mechanisms (either by calling it directly, or by referring to its
|
||||||
implementation for details of the required state updates).
|
implementation for details of the required state updates).
|
||||||
|
|
||||||
|
The caller must hold the GIL.
|
||||||
|
|
||||||
Return 0 on success or -1 on failure.
|
Return 0 on success or -1 on failure.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
@ -536,4 +538,6 @@ since multiple such modules can be created from a single definition.
|
||||||
Removes the module object created from *def* from the interpreter state.
|
Removes the module object created from *def* from the interpreter state.
|
||||||
Return 0 on success or -1 on failure.
|
Return 0 on success or -1 on failure.
|
||||||
|
|
||||||
|
The caller must hold the GIL.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
108
Python/pystate.c
108
Python/pystate.c
|
@ -8,6 +8,7 @@
|
||||||
#include "pycore_pylifecycle.h"
|
#include "pycore_pylifecycle.h"
|
||||||
#include "pycore_pymem.h"
|
#include "pycore_pymem.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
|
#include "pycore_sysmodule.h"
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
CAUTION
|
CAUTION
|
||||||
|
@ -203,7 +204,10 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime)
|
||||||
PyInterpreterState *
|
PyInterpreterState *
|
||||||
PyInterpreterState_New(void)
|
PyInterpreterState_New(void)
|
||||||
{
|
{
|
||||||
if (PySys_Audit("cpython.PyInterpreterState_New", NULL) < 0) {
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
/* tstate is NULL when Py_InitializeFromConfig() calls
|
||||||
|
PyInterpreterState_New() to create the main interpreter. */
|
||||||
|
if (_PySys_Audit(tstate, "cpython.PyInterpreterState_New", NULL) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +218,7 @@ PyInterpreterState_New(void)
|
||||||
|
|
||||||
interp->id_refcount = -1;
|
interp->id_refcount = -1;
|
||||||
|
|
||||||
|
/* Don't get runtime from tstate since tstate can be NULL */
|
||||||
_PyRuntimeState *runtime = &_PyRuntime;
|
_PyRuntimeState *runtime = &_PyRuntime;
|
||||||
interp->runtime = runtime;
|
interp->runtime = runtime;
|
||||||
|
|
||||||
|
@ -235,8 +240,10 @@ PyInterpreterState_New(void)
|
||||||
HEAD_LOCK(runtime);
|
HEAD_LOCK(runtime);
|
||||||
if (interpreters->next_id < 0) {
|
if (interpreters->next_id < 0) {
|
||||||
/* overflow or Py_Initialize() not called! */
|
/* overflow or Py_Initialize() not called! */
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
if (tstate != NULL) {
|
||||||
"failed to get an interpreter ID");
|
_PyErr_SetString(tstate, PyExc_RuntimeError,
|
||||||
|
"failed to get an interpreter ID");
|
||||||
|
}
|
||||||
PyMem_RawFree(interp);
|
PyMem_RawFree(interp);
|
||||||
interp = NULL;
|
interp = NULL;
|
||||||
}
|
}
|
||||||
|
@ -268,8 +275,11 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
_PyRuntimeState *runtime = interp->runtime;
|
_PyRuntimeState *runtime = interp->runtime;
|
||||||
|
|
||||||
if (PySys_Audit("cpython.PyInterpreterState_Clear", NULL) < 0) {
|
/* Use the current Python thread state to call audit hooks,
|
||||||
PyErr_Clear();
|
not the current Python thread state of 'interp'. */
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (_PySys_Audit(tstate, "cpython.PyInterpreterState_Clear", NULL) < 0) {
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
HEAD_LOCK(runtime);
|
HEAD_LOCK(runtime);
|
||||||
|
@ -655,12 +665,13 @@ int
|
||||||
_PyState_AddModule(PyThreadState *tstate, PyObject* module, struct PyModuleDef* def)
|
_PyState_AddModule(PyThreadState *tstate, PyObject* module, struct PyModuleDef* def)
|
||||||
{
|
{
|
||||||
if (!def) {
|
if (!def) {
|
||||||
assert(PyErr_Occurred());
|
assert(_PyErr_Occurred(tstate));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (def->m_slots) {
|
if (def->m_slots) {
|
||||||
PyErr_SetString(PyExc_SystemError,
|
_PyErr_SetString(tstate,
|
||||||
"PyState_AddModule called on module with slots");
|
PyExc_SystemError,
|
||||||
|
"PyState_AddModule called on module with slots");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,28 +718,29 @@ PyState_AddModule(PyObject* module, struct PyModuleDef* def)
|
||||||
int
|
int
|
||||||
PyState_RemoveModule(struct PyModuleDef* def)
|
PyState_RemoveModule(struct PyModuleDef* def)
|
||||||
{
|
{
|
||||||
PyInterpreterState *state;
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t index = def->m_base.m_index;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
|
|
||||||
if (def->m_slots) {
|
if (def->m_slots) {
|
||||||
PyErr_SetString(PyExc_SystemError,
|
_PyErr_SetString(tstate,
|
||||||
"PyState_RemoveModule called on module with slots");
|
PyExc_SystemError,
|
||||||
|
"PyState_RemoveModule called on module with slots");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
state = _PyInterpreterState_GET_UNSAFE();
|
|
||||||
|
Py_ssize_t index = def->m_base.m_index;
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
Py_FatalError("invalid module index");
|
Py_FatalError("invalid module index");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (state->modules_by_index == NULL) {
|
if (interp->modules_by_index == NULL) {
|
||||||
Py_FatalError("Interpreters module-list not accessible.");
|
Py_FatalError("Interpreters module-list not accessible.");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (index > PyList_GET_SIZE(state->modules_by_index)) {
|
if (index > PyList_GET_SIZE(interp->modules_by_index)) {
|
||||||
Py_FatalError("Module index out of bounds.");
|
Py_FatalError("Module index out of bounds.");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return PyList_SetItem(state->modules_by_index, index, Py_None);
|
return PyList_SetItem(interp->modules_by_index, index, Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used by PyImport_Cleanup() */
|
/* Used by PyImport_Cleanup() */
|
||||||
|
@ -1114,16 +1126,15 @@ PyThreadState_Next(PyThreadState *tstate) {
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyThread_CurrentFrames(void)
|
_PyThread_CurrentFrames(void)
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
PyInterpreterState *i;
|
if (_PySys_Audit(tstate, "sys._current_frames", NULL) < 0) {
|
||||||
|
|
||||||
if (PySys_Audit("sys._current_frames", NULL) < 0) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = PyDict_New();
|
PyObject *result = PyDict_New();
|
||||||
if (result == NULL)
|
if (result == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* for i in all interpreters:
|
/* for i in all interpreters:
|
||||||
* for t in all of i's thread states:
|
* for t in all of i's thread states:
|
||||||
|
@ -1131,32 +1142,35 @@ _PyThread_CurrentFrames(void)
|
||||||
* Because these lists can mutate even when the GIL is held, we
|
* Because these lists can mutate even when the GIL is held, we
|
||||||
* need to grab head_mutex for the duration.
|
* need to grab head_mutex for the duration.
|
||||||
*/
|
*/
|
||||||
_PyRuntimeState *runtime = &_PyRuntime;
|
_PyRuntimeState *runtime = tstate->interp->runtime;
|
||||||
HEAD_LOCK(runtime);
|
HEAD_LOCK(runtime);
|
||||||
|
PyInterpreterState *i;
|
||||||
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
|
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
|
||||||
PyThreadState *t;
|
PyThreadState *t;
|
||||||
for (t = i->tstate_head; t != NULL; t = t->next) {
|
for (t = i->tstate_head; t != NULL; t = t->next) {
|
||||||
PyObject *id;
|
|
||||||
int stat;
|
|
||||||
struct _frame *frame = t->frame;
|
struct _frame *frame = t->frame;
|
||||||
if (frame == NULL)
|
if (frame == NULL) {
|
||||||
continue;
|
continue;
|
||||||
id = PyLong_FromUnsignedLong(t->thread_id);
|
}
|
||||||
if (id == NULL)
|
PyObject *id = PyLong_FromUnsignedLong(t->thread_id);
|
||||||
goto Fail;
|
if (id == NULL) {
|
||||||
stat = PyDict_SetItem(result, id, (PyObject *)frame);
|
goto fail;
|
||||||
|
}
|
||||||
|
int stat = PyDict_SetItem(result, id, (PyObject *)frame);
|
||||||
Py_DECREF(id);
|
Py_DECREF(id);
|
||||||
if (stat < 0)
|
if (stat < 0) {
|
||||||
goto Fail;
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
Py_CLEAR(result);
|
||||||
|
|
||||||
|
done:
|
||||||
HEAD_UNLOCK(runtime);
|
HEAD_UNLOCK(runtime);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Fail:
|
|
||||||
HEAD_UNLOCK(runtime);
|
|
||||||
Py_DECREF(result);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Python "auto thread state" API. */
|
/* Python "auto thread state" API. */
|
||||||
|
@ -1436,19 +1450,19 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_check_xidata(_PyCrossInterpreterData *data)
|
_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data)
|
||||||
{
|
{
|
||||||
// data->data can be anything, including NULL, so we don't check it.
|
// data->data can be anything, including NULL, so we don't check it.
|
||||||
|
|
||||||
// data->obj may be NULL, so we don't check it.
|
// data->obj may be NULL, so we don't check it.
|
||||||
|
|
||||||
if (data->interp < 0) {
|
if (data->interp < 0) {
|
||||||
PyErr_SetString(PyExc_SystemError, "missing interp");
|
_PyErr_SetString(tstate, PyExc_SystemError, "missing interp");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->new_object == NULL) {
|
if (data->new_object == NULL) {
|
||||||
PyErr_SetString(PyExc_SystemError, "missing new_object func");
|
_PyErr_SetString(tstate, PyExc_SystemError, "missing new_object func");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1460,9 +1474,9 @@ _check_xidata(_PyCrossInterpreterData *data)
|
||||||
int
|
int
|
||||||
_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
|
_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
|
||||||
{
|
{
|
||||||
// PyInterpreterState_Get() aborts if lookup fails, so we don't need
|
// PyThreadState_Get() aborts if tstate is NULL.
|
||||||
// to check the result for NULL.
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = tstate->interp;
|
||||||
|
|
||||||
// Reset data before re-populating.
|
// Reset data before re-populating.
|
||||||
*data = (_PyCrossInterpreterData){0};
|
*data = (_PyCrossInterpreterData){0};
|
||||||
|
@ -1483,7 +1497,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
|
||||||
|
|
||||||
// Fill in the blanks and validate the result.
|
// Fill in the blanks and validate the result.
|
||||||
data->interp = interp->id;
|
data->interp = interp->id;
|
||||||
if (_check_xidata(data) != 0) {
|
if (_check_xidata(tstate, data) != 0) {
|
||||||
_PyCrossInterpreterData_Release(data);
|
_PyCrossInterpreterData_Release(data);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue