-
-
Notifications
You must be signed in to change notification settings - Fork 31.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-124622: Add PyGILState_EnsureOrFail() function #129688
Conversation
Add new "OrFail" functions: * _PyEval_AcquireLockOrFail() * _PyEval_RestoreThreadOrFail() * _PyThreadState_AttachOrFail() * take_gil_or_fail()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said in the issue, I really don't want new GILState APIs, because they're quite broken for subinterpreters and misleading for free-threading (FT users sometimes think they don't need a tstate to use the C API).
I'd rather call this PyThreadState_Ensure
, or something along those lines, and then deprecate PyGILState
. cc @encukou
Doc/c-api/init.rst
Outdated
Similar to :c:func:`PyGILState_Ensure`, but *state* is an argument | ||
and return ``-1`` if the thread must exit. Return ``0`` on success. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing and misleading. The C or C++ thread must not exit. It's just that the function failed taking the GIL, probably because Python is finalized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on the principle, but see comments below.
2cts from me: for this to be useful for extensions, it would be good if it is immediately part of the stable ABI. The implementation looks fine except for comment describing the function. I would change it to:
|
Ok, done.
Done. |
If we adopt a different API, I would suggest avoiding also the enum, use a simple API:
API: Usage: int state = PyThreadState_Ensure();
if (state < 0) return;
// ... use the Python C API ...
PyThreadState_Release(state); |
I'd also prefer that, but AFAIK such a function would need an extra argument (to specify which interpreter you want to end up in). Is that right? As an incremental improvement for current users of Could you add the mention that these are “not compatible with sub-interpreters” directly to the docs? This should go through the C API WG. |
Which API should be recommended instead, if this one is not compatible with sub-interpreters? |
|
PyThreadState_Swap() requires a tstate. How do you create the tstate in a new thread to support sub-interpreters? |
I think turning this API into |
Indeed it might be a good idea to add: int PyThreadState_Ensure(PyInterpreterState*);
void PyThreadState_Release(int state, PyInterpreterState*); |
An |
I created #130012 to add PyThreadState_Ensure() and PyThreadState_Release() functions. |
In the case of failure, it is *unsafe* to use the Python API following the | ||
call. Releasing the obtained *state* via :c:func:`PyGILState_Release` should | ||
only be done in the case of success. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add the mention that these are “not compatible with sub-interpreters” directly to the docs?
Which API should be recommended instead, if this one is not compatible with sub-interpreters?
I meant repeating the note above PyGILState_Ensure
that says The following functions use thread-local storage, and are not compatible with sub-interpreters:. Users that click the What's New link go directly to the function docs and are quite likely to miss the warning.
Something like:
Like :c:func:`!PyGILState_Ensure`, this function is not safe to use with | |
supinterpreters, since it is not possible to specify which interpreter | |
is activated. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#130012 PR should be subinterpreter-friendly, I closed this PR instead.
operation succeeded, and ``-1`` otherwise. In contrast to | ||
:c:func:`PyGILState_Ensure`, *state* is an argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
operation succeeded, and ``-1`` otherwise. In contrast to | |
:c:func:`PyGILState_Ensure`, *state* is an argument. | |
operation succeeded, and ``-1`` otherwise. | |
The return value of :c:func:`!PyGILState_Ensure` | |
is stored in *\*state*. |
:c:func:`PyGILState_Ensure`, *state* is an argument. | ||
|
||
In the case of failure, it is *unsafe* to use the Python API following the | ||
call. Releasing the obtained *state* via :c:func:`PyGILState_Release` should |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
call. Releasing the obtained *state* via :c:func:`PyGILState_Release` should | |
call. Releasing the obtained *state* via :c:func:`PyGILState_Release` must |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied this suggestion to #130012 since I closed this PR.
It seems like the trend is more towards passing interp explicitly, so I close this PR. |
Add new "OrFail" functions:
📚 Documentation preview 📚: https://cpython-previews--129688.org.readthedocs.build/