Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4e88c2b
Always wait for threads in subinterpreters.
ericsnowcurrently Sep 25, 2023
d08ac68
Add PyInterpreterState_*RunningMain().
ericsnowcurrently Sep 26, 2023
3b07482
Drop interpreter_exists().
ericsnowcurrently Sep 26, 2023
70c4753
Drop PyThreadState_IsRunning().
ericsnowcurrently Sep 26, 2023
678cb3b
Add a TODO.
ericsnowcurrently Sep 26, 2023
5be5a07
For now use the earliest thread state.
ericsnowcurrently Sep 26, 2023
81a1e0b
Add tests.
ericsnowcurrently Sep 26, 2023
c3f497b
Mark the main interpreter as running __main__.
ericsnowcurrently Sep 26, 2023
effa5b4
Call PyInterpreterState_SetNotRunningMain() in the right place.
ericsnowcurrently Sep 26, 2023
41c54b0
Check PyInterpreterState_IsRunningMain() preemptively, for now.
ericsnowcurrently Sep 26, 2023
5fbd940
Add docs.
ericsnowcurrently Sep 26, 2023
8b54c2e
Add a NEWS entry.
ericsnowcurrently Sep 26, 2023
5d1df61
Fix a typo.
ericsnowcurrently Sep 27, 2023
1034a67
Update the docs.
ericsnowcurrently Sep 27, 2023
d57729e
Update the docs.
ericsnowcurrently Sep 27, 2023
4219e2c
Update the docs.
ericsnowcurrently Sep 27, 2023
bfdace2
Drop a dead line.
ericsnowcurrently Sep 27, 2023
ef8af92
Drop an unused parameter.
ericsnowcurrently Sep 27, 2023
566cd08
Drop an unnecessary variable.
ericsnowcurrently Sep 27, 2023
d14b87a
Update TODO comments.
ericsnowcurrently Sep 27, 2023
1f2a321
Merge branch 'main' into subinterpreters-allow-background-threads
ericsnowcurrently Sep 27, 2023
55d7090
Merge branch 'main' into subinterpreters-allow-background-threads
ericsnowcurrently Sep 29, 2023
399859f
Do not expose the "Running" C-API (for now).
ericsnowcurrently Oct 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Do not expose the "Running" C-API (for now).
  • Loading branch information
ericsnowcurrently committed Oct 2, 2023
commit 399859f5906ac4af410984c8d090850a0dd13644
74 changes: 0 additions & 74 deletions Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1115,80 +1115,6 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. versionadded:: 3.7


.. c:function:: int PyInterpreterState_SetRunningMain(PyInterpreterState *interp)

Indicate that the current thread will be running the "main" Python
program (e.g. script) for the given interpreter. This typically
means executing Python code against the ``__main__`` module of
the interpreter, e.g. using :c:func:`PyRun_SimpleString`.

Only one thread may be "main" at a time for each interpreter.
Thus, this should not be called in subthreads created by the program.
If the interpreter is already marked as running then this function
will raise :exc:`RuntimeError` (even if in the same thread where
it was called earlier).

Every call to this function must have a corresponding call to
:c:func:`PyInterpreterState_UnsetRunningMain`. The pairs of calls
may happen any number of times.

Subthreads from a previous "main" execution may still be running
when this is called. Likewise, the interpreter is not required
to be in a pristine condition and may still hold state and objects
from an earlier "main".

Before running a Python program, there are often a number of
interactions with the runtime, sometimes even including running
non-"main" Python code. Calling this function first before doing
them is not necessary, as long as it is called before running the
program itself.

The caller must hold the GIL.

This function is intended for use in embedded applications or by
extension modules that manage subinterpreters.

.. versionadded:: 3.13


.. c:function:: void PyInterpreterState_UnsetRunningMain(PyInterpreterState *interp)

Indicate that the current thread is done running the "main" Python
program for the given interpreter. This is the companion to
:c:func:`PyInterpreterState_SetRunningMain`.

Subthreads created by the program may still be running when this
is called. Likewise, the interpreter's state is neither reset nor
required to be reset.

The caller must hold the GIL.

This function is intended for use in embedded applications
or by extension modules that manage subinterpreters.

.. versionadded:: 3.13


.. c:function:: int PyInterpreterState_IsRunningMain(PyInterpreterState *interp)

Return true (nonzero) if the interpreter is currently running
a "main" Python program in one of its threads, false (zero) if not.
See :c:func:`PyInterpreterState_SetRunningMain`.

This relates only to the thread where the program started,
not subthreads. An interpreter may still have subthreads running
even if this returns false.

The caller must hold the GIL.

This function will typically only be useful for embedded applications
or extension modules that manage subinterpreters. For other cases
expect that this would always return true, since the application
or subinterpreters extension should have already set it.

.. versionadded:: 3.13


.. c:function:: PyObject* PyInterpreterState_GetDict(PyInterpreterState *interp)

Return a dictionary in which interpreter-specific data may be stored.
Expand Down
4 changes: 0 additions & 4 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,6 @@ struct _ts {
* if it is NULL. */
PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void);

PyAPI_FUNC(int) PyInterpreterState_SetRunningMain(PyInterpreterState *);
PyAPI_FUNC(void) PyInterpreterState_SetNotRunningMain(PyInterpreterState *);
PyAPI_FUNC(int) PyInterpreterState_IsRunningMain(PyInterpreterState *);


// Disable tracing and profiling.
PyAPI_FUNC(void) PyThreadState_EnterTracing(PyThreadState *tstate);
Expand Down
5 changes: 5 additions & 0 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ _Py_IsMainInterpreterFinalizing(PyInterpreterState *interp)
interp == &_PyRuntime._main_interpreter);
}

// Export for _xxsubinterpreters module.
PyAPI_FUNC(int) _PyInterpreterState_SetRunningMain(PyInterpreterState *);
PyAPI_FUNC(void) _PyInterpreterState_SetNotRunningMain(PyInterpreterState *);
PyAPI_FUNC(int) _PyInterpreterState_IsRunningMain(PyInterpreterState *);


static inline const PyConfig *
_Py_GetMainConfig(void)
Expand Down
13 changes: 7 additions & 6 deletions Modules/_xxsubinterpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Python.h"
#include "pycore_initconfig.h" // _PyErr_SetFromPyStatus()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain()
#include "interpreteridobject.h"


Expand Down Expand Up @@ -361,7 +362,7 @@ static int
_run_script(PyInterpreterState *interp, const char *codestr,
_sharedns *shared, _sharedexception *sharedexc)
{
if (PyInterpreterState_SetRunningMain(interp) < 0) {
if (_PyInterpreterState_SetRunningMain(interp) < 0) {
// We skip going through the shared exception.
return -1;
}
Expand Down Expand Up @@ -395,7 +396,7 @@ _run_script(PyInterpreterState *interp, const char *codestr,
else {
Py_DECREF(result); // We throw away the result.
}
PyInterpreterState_SetNotRunningMain(interp);
_PyInterpreterState_SetNotRunningMain(interp);

*sharedexc = no_exception;
return 0;
Expand All @@ -411,7 +412,7 @@ _run_script(PyInterpreterState *interp, const char *codestr,
}
Py_XDECREF(excval);
assert(!PyErr_Occurred());
PyInterpreterState_SetNotRunningMain(interp);
_PyInterpreterState_SetNotRunningMain(interp);
return -1;
}

Expand Down Expand Up @@ -441,7 +442,7 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp,
// exception gets raised in the right one.
// XXX gh-109860: Drop this redundant check once we stop
// re-using tstates that might already be in use.
if (PyInterpreterState_IsRunningMain(interp)) {
if (_PyInterpreterState_IsRunningMain(interp)) {
PyErr_SetString(PyExc_RuntimeError,
"interpreter already running");
if (shared != NULL) {
Expand Down Expand Up @@ -566,7 +567,7 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
// Ensure the interpreter isn't running.
/* XXX We *could* support destroying a running interpreter but
aren't going to worry about it for now. */
if (PyInterpreterState_IsRunningMain(interp)) {
if (_PyInterpreterState_IsRunningMain(interp)) {
PyErr_Format(PyExc_RuntimeError, "interpreter running");
return NULL;
}
Expand Down Expand Up @@ -748,7 +749,7 @@ interp_is_running(PyObject *self, PyObject *args, PyObject *kwds)
if (interp == NULL) {
return NULL;
}
if (PyInterpreterState_IsRunningMain(interp)) {
if (_PyInterpreterState_IsRunningMain(interp)) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
Expand Down
4 changes: 2 additions & 2 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ pymain_run_python(int *exitcode)

pymain_header(config);

PyInterpreterState_SetRunningMain(interp);
_PyInterpreterState_SetRunningMain(interp);
assert(!PyErr_Occurred());

if (config->run_command) {
Expand All @@ -620,7 +620,7 @@ pymain_run_python(int *exitcode)
*exitcode = pymain_exit_err_print();

done:
PyInterpreterState_SetNotRunningMain(interp);
_PyInterpreterState_SetNotRunningMain(interp);
Py_XDECREF(main_importer_path);
}

Expand Down
6 changes: 3 additions & 3 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)


int
PyInterpreterState_SetRunningMain(PyInterpreterState *interp)
_PyInterpreterState_SetRunningMain(PyInterpreterState *interp)
{
if (interp->threads.main != NULL) {
PyErr_SetString(PyExc_RuntimeError,
Expand All @@ -1111,14 +1111,14 @@ PyInterpreterState_SetRunningMain(PyInterpreterState *interp)
}

void
PyInterpreterState_SetNotRunningMain(PyInterpreterState *interp)
_PyInterpreterState_SetNotRunningMain(PyInterpreterState *interp)
{
assert(interp->threads.main == current_fast_get(&_PyRuntime));
interp->threads.main = NULL;
}

int
PyInterpreterState_IsRunningMain(PyInterpreterState *interp)
_PyInterpreterState_IsRunningMain(PyInterpreterState *interp)
{
return (interp->threads.main != NULL);
}
Expand Down