mirror of https://github.com/python/cpython
GH-104668: Don't call PyOS_* hooks in subinterpreters (GH-104674)
This commit is contained in:
parent
2c4e29e322
commit
357bed0bcd
|
@ -167,6 +167,10 @@ the same library that the Python runtime is using.
|
||||||
event loops, as done in the :file:`Modules/_tkinter.c` in the
|
event loops, as done in the :file:`Modules/_tkinter.c` in the
|
||||||
Python source code.
|
Python source code.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.12
|
||||||
|
This function is only called from the
|
||||||
|
:ref:`main interpreter <sub-interpreter-support>`.
|
||||||
|
|
||||||
|
|
||||||
.. c:var:: char* (*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *)
|
.. c:var:: char* (*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *)
|
||||||
|
|
||||||
|
@ -187,6 +191,10 @@ the same library that the Python runtime is using.
|
||||||
:c:func:`PyMem_RawRealloc`, instead of being allocated by
|
:c:func:`PyMem_RawRealloc`, instead of being allocated by
|
||||||
:c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`.
|
:c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.12
|
||||||
|
This function is only called from the
|
||||||
|
:ref:`main interpreter <sub-interpreter-support>`.
|
||||||
|
|
||||||
.. c:function:: PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
|
.. c:function:: PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
|
||||||
|
|
||||||
This is a simplified interface to :c:func:`PyRun_StringFlags` below, leaving
|
This is a simplified interface to :c:func:`PyRun_StringFlags` below, leaving
|
||||||
|
|
|
@ -1476,6 +1476,15 @@ Porting to Python 3.12
|
||||||
Note that :c:func:`PyType_FromMetaclass` (added in Python 3.12)
|
Note that :c:func:`PyType_FromMetaclass` (added in Python 3.12)
|
||||||
already disallows creating classes whose metaclass overrides ``tp_new``.
|
already disallows creating classes whose metaclass overrides ``tp_new``.
|
||||||
|
|
||||||
|
* :c:var:`PyOS_InputHook` and :c:var:`PyOS_ReadlineFunctionPointer` are no
|
||||||
|
longer called in :ref:`subinterpreters <sub-interpreter-support>`. This is
|
||||||
|
because clients generally rely on process-wide global state (since these
|
||||||
|
callbacks have no way of recovering extension module state).
|
||||||
|
|
||||||
|
This also avoids situations where extensions may find themselves running in a
|
||||||
|
subinterpreter that they don't support (or haven't yet been loaded in). See
|
||||||
|
:gh:`104668` for more info.
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Don't call :c:var:`PyOS_InputHook` or :c:var:`PyOS_ReadlineFunctionPointer`
|
||||||
|
in subinterpreters, since it's generally difficult to avoid using global
|
||||||
|
state in their registered callbacks. This also avoids situations where
|
||||||
|
extensions may find themselves running in a subinterpreter they don't
|
||||||
|
support (or haven't yet been loaded in).
|
|
@ -45,7 +45,10 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (PyOS_InputHook != NULL) {
|
if (PyOS_InputHook != NULL &&
|
||||||
|
// GH-104668: See PyOS_ReadlineFunctionPointer's comment below...
|
||||||
|
_Py_IsMainInterpreter(tstate->interp))
|
||||||
|
{
|
||||||
(void)(PyOS_InputHook)();
|
(void)(PyOS_InputHook)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +134,10 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn)
|
||||||
wbuf = wbuf_local;
|
wbuf = wbuf_local;
|
||||||
wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1;
|
wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (PyOS_InputHook != NULL) {
|
if (PyOS_InputHook != NULL &&
|
||||||
|
// GH-104668: See PyOS_ReadlineFunctionPointer's comment below...
|
||||||
|
_Py_IsMainInterpreter(tstate->interp))
|
||||||
|
{
|
||||||
(void)(PyOS_InputHook)();
|
(void)(PyOS_InputHook)();
|
||||||
}
|
}
|
||||||
if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
|
if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
|
||||||
|
@ -389,11 +395,23 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
||||||
* a tty. This can happen, for example if python is run like
|
* a tty. This can happen, for example if python is run like
|
||||||
* this: python -i < test1.py
|
* this: python -i < test1.py
|
||||||
*/
|
*/
|
||||||
if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
|
if (!isatty(fileno(sys_stdin)) || !isatty(fileno(sys_stdout)) ||
|
||||||
|
// GH-104668: Don't call global callbacks like PyOS_InputHook or
|
||||||
|
// PyOS_ReadlineFunctionPointer from subinterpreters, since it seems
|
||||||
|
// like there's no good way for users (like readline and tkinter) to
|
||||||
|
// avoid using global state to manage them. Plus, we generally don't
|
||||||
|
// want to cause trouble for libraries that don't know/care about
|
||||||
|
// subinterpreter support. If libraries really need better APIs that
|
||||||
|
// work per-interpreter and have ways to access module state, we can
|
||||||
|
// certainly add them later (but for now we'll cross our fingers and
|
||||||
|
// hope that nobody actually cares):
|
||||||
|
!_Py_IsMainInterpreter(tstate->interp))
|
||||||
|
{
|
||||||
rv = PyOS_StdioReadline(sys_stdin, sys_stdout, prompt);
|
rv = PyOS_StdioReadline(sys_stdin, sys_stdout, prompt);
|
||||||
else
|
}
|
||||||
rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
|
else {
|
||||||
prompt);
|
rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, prompt);
|
||||||
|
}
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
PyThread_release_lock(_PyOS_ReadlineLock);
|
PyThread_release_lock(_PyOS_ReadlineLock);
|
||||||
|
|
Loading…
Reference in New Issue