Skip to content

Commit

Permalink
pythongh-106320: Remove private _PyInterpreterState functions
Browse files Browse the repository at this point in the history
Remove private _PyThreadState and _PyInterpreterState C API
functions: move them to the internal C API (pycore_pystate.h and
pycore_interp.h). Don't export most of these functions anymore, but
still export functions used by tests.

Remove _PyThreadState_Prealloc() and _PyThreadState_Init() from the C
API, but keep it in the stable API.
  • Loading branch information
vstinner committed Jul 2, 2023
1 parent feb51f3 commit 94979be
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 70 deletions.
57 changes: 0 additions & 57 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ PyAPI_FUNC(int) _PyInterpreterState_HasFeature(PyInterpreterState *interp,
PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *);
PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int);

PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *);


/* State unique per thread */

Expand Down Expand Up @@ -261,16 +259,10 @@ struct _ts {

/* other API */

/* An alias for the internal _PyThreadState_New(),
kept for stable ABI compatibility. */
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);

/* Similar to PyThreadState_Get(), but don't issue a fatal error
* if it is NULL. */
PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void);

PyAPI_FUNC(PyObject *) _PyThreadState_GetDict(PyThreadState *tstate);

// Disable tracing and profiling.
PyAPI_FUNC(void) PyThreadState_EnterTracing(PyThreadState *tstate);

Expand All @@ -295,16 +287,6 @@ PyAPI_FUNC(int) PyGILState_Check(void);
See also PyInterpreterState_Get() and _PyInterpreterState_GET(). */
PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void);

/* The implementation of sys._current_frames() Returns a dict mapping
thread id to that thread's current frame.
*/
PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void);

/* The implementation of sys._current_exceptions() Returns a dict mapping
thread id to that thread's current exception.
*/
PyAPI_FUNC(PyObject *) _PyThread_CurrentExceptions(void);

/* Routines for advanced debuggers, requested by David Beazley.
Don't use unless you know what you are doing! */
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Main(void);
Expand All @@ -324,45 +306,6 @@ PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc(
PyInterpreterState *interp,
_PyFrameEvalFunction eval_frame);

PyAPI_FUNC(const PyConfig*) _PyInterpreterState_GetConfig(PyInterpreterState *interp);

/* Get a copy of the current interpreter configuration.
Return 0 on success. Raise an exception and return -1 on error.
The caller must initialize 'config', using PyConfig_InitPythonConfig()
for example.
Python must be preinitialized to call this method.
The caller must hold the GIL.
Once done with the configuration, PyConfig_Clear() must be called to clear
it. */
PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy(
struct PyConfig *config);

/* Set the configuration of the current interpreter.
This function should be called during or just after the Python
initialization.
Update the sys module with the new configuration. If the sys module was
modified directly after the Python initialization, these changes are lost.
Some configuration like faulthandler or warnoptions can be updated in the
configuration, but don't reconfigure Python (don't enable/disable
faulthandler and don't reconfigure warnings filters).
Return 0 on success. Raise an exception and return -1 on error.
The configuration should come from _PyInterpreterState_GetConfigCopy(). */
PyAPI_FUNC(int) _PyInterpreterState_SetConfig(
const struct PyConfig *config);

// Get the configuration of the current interpreter.
// The caller must hold the GIL.
PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);


/* cross-interpreter data */

Expand Down
37 changes: 37 additions & 0 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,43 @@ PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *);
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *);
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *);

PyAPI_FUNC(PyObject*) _PyInterpreterState_GetMainModule(PyInterpreterState *);

extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp);

/* Get a copy of the current interpreter configuration.
Return 0 on success. Raise an exception and return -1 on error.
The caller must initialize 'config', using PyConfig_InitPythonConfig()
for example.
Python must be preinitialized to call this method.
The caller must hold the GIL.
Once done with the configuration, PyConfig_Clear() must be called to clear
it. */
PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy(
struct PyConfig *config);

/* Set the configuration of the current interpreter.
This function should be called during or just after the Python
initialization.
Update the sys module with the new configuration. If the sys module was
modified directly after the Python initialization, these changes are lost.
Some configuration like faulthandler or warnoptions can be updated in the
configuration, but don't reconfigure Python (don't enable/disable
faulthandler and don't reconfigure warnings filters).
Return 0 on success. Raise an exception and return -1 on error.
The configuration should come from _PyInterpreterState_GetConfigCopy(). */
PyAPI_FUNC(int) _PyInterpreterState_SetConfig(
const struct PyConfig *config);

#ifdef __cplusplus
}
#endif
Expand Down
19 changes: 16 additions & 3 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,25 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) {

PyAPI_FUNC(PyThreadState *) _PyThreadState_New(PyInterpreterState *interp);
PyAPI_FUNC(void) _PyThreadState_Bind(PyThreadState *tstate);
// We keep this around exclusively for stable ABI compatibility.
PyAPI_FUNC(void) _PyThreadState_Init(
PyThreadState *tstate);
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);

extern void _PyThreadState_InitDetached(PyThreadState *, PyInterpreterState *);
extern void _PyThreadState_ClearDetached(PyThreadState *);
extern void _PyThreadState_BindDetached(PyThreadState *);
extern void _PyThreadState_UnbindDetached(PyThreadState *);

PyAPI_FUNC(PyObject*) _PyThreadState_GetDict(PyThreadState *tstate);

/* The implementation of sys._current_frames() Returns a dict mapping
thread id to that thread's current frame.
*/
extern PyObject* _PyThread_CurrentFrames(void);

/* The implementation of sys._current_exceptions() Returns a dict mapping
thread id to that thread's current exception.
*/
extern PyObject* _PyThread_CurrentExceptions(void);


/* Other */

Expand Down Expand Up @@ -161,6 +170,10 @@ PyAPI_FUNC(int) _PyOS_InterruptOccurred(PyThreadState *tstate);
#define HEAD_UNLOCK(runtime) \
PyThread_release_lock((runtime)->interpreters.mutex)

// Get the configuration of the current interpreter.
// The caller must hold the GIL.
PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);


#ifdef __cplusplus
}
Expand Down
5 changes: 0 additions & 5 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2714,11 +2714,6 @@ test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
assert(PyDict_Check(dict));
// dict is a borrowed reference

// private _PyThreadState_GetDict()
PyObject *dict2 = _PyThreadState_GetDict(tstate);
assert(dict2 == dict);
// dict2 is a borrowed reference

// PyThreadState_GetInterpreter()
PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
assert(interp != NULL);
Expand Down
22 changes: 22 additions & 0 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,27 @@ tracemalloc_get_traceback(PyObject *self, PyObject *args)
}


// Test PyThreadState C API
static PyObject *
test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
{
// PyThreadState_Get()
PyThreadState *tstate = PyThreadState_Get();
assert(tstate != NULL);

// test _PyThreadState_GetDict()
PyObject *dict = PyThreadState_GetDict();
assert(dict != NULL);
// dict is a borrowed reference

PyObject *dict2 = _PyThreadState_GetDict(tstate);
assert(dict2 == dict);
// dict2 is a borrowed reference

Py_RETURN_NONE;
}


static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
Expand Down Expand Up @@ -1284,6 +1305,7 @@ static PyMethodDef module_functions[] = {
{"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS},
{"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS},
{"_PyTraceMalloc_GetTraceback", tracemalloc_get_traceback, METH_VARARGS},
{"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */
};

Expand Down
6 changes: 5 additions & 1 deletion Modules/_xxsubinterpretersmodule.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@

/* interpreters module */
/* low-level access to interpreter primitives */

#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif

#include "Python.h"
#include "pycore_interp.h" // _PyInterpreterState_GetMainModule()
#include "interpreteridobject.h"


Expand Down
1 change: 1 addition & 0 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "pycore_compile.h"
#include "pycore_intrinsics.h"
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_pystate.h" // _Py_GetConfig()
#include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST()

#include "opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
Expand Down
3 changes: 2 additions & 1 deletion Python/frozenmain.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* Python interpreter main program for frozen scripts */

#include "Python.h"
#include "pycore_runtime.h" // _PyRuntime_Initialize()
#include "pycore_pystate.h" // _Py_GetConfig()
#include "pycore_runtime.h" // _PyRuntime_Initialize()
#include <locale.h>

#ifdef MS_WINDOWS
Expand Down
6 changes: 3 additions & 3 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ PyInterpreterState_GetDict(PyInterpreterState *interp)
The GIL must be held.
*/

PyInterpreterState *
PyInterpreterState*
PyInterpreterState_Get(void)
{
PyThreadState *tstate = current_fast_get(&_PyRuntime);
Expand Down Expand Up @@ -1408,15 +1408,15 @@ _PyThreadState_New(PyInterpreterState *interp)
}

// We keep this for stable ABI compabibility.
PyThreadState *
PyAPI_FUNC(PyThreadState*)
_PyThreadState_Prealloc(PyInterpreterState *interp)
{
return _PyThreadState_New(interp);
}

// We keep this around for (accidental) stable ABI compatibility.
// Realistically, no extensions are using it.
void
PyAPI_FUNC(void)
_PyThreadState_Init(PyThreadState *tstate)
{
Py_FatalError("_PyThreadState_Init() is for internal use only");
Expand Down

0 comments on commit 94979be

Please sign in to comment.