GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-108867: Add PyThreadState_GetUnchecked() function by vstinner · Pull Request #108870 · python/cpython

Conversation

@vstinner

@vstinner vstinner commented Sep 4, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Add PyThreadState_GetUnchecked() function: similar to
PyThreadState_Get(), but don't issue a fatal error if it is NULL. The
caller is responsible to check if the result is NULL. Previously,
this function was private and known as _PyThreadState_UncheckedGet().

  • Issue: C API: Rename _PyThreadState_GetUnchecked() to public PyThreadState_GetUnchecked #108867

📚 Documentation preview 📚: https://cpython-previews--108870.org.readthedocs.build/

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot added the awaiting core review label Sep 4, 2023
@bedevere-bot bedevere-bot mentioned this pull request Sep 4, 2023
C API: Rename _PyThreadState_GetUnchecked() to public PyThreadState_GetUnchecked #108867
Closed
@vstinner
vstinner force-pushed the tstate_getunsafe branch 2 times, most recently from c180b5b to 572f4a4 Compare September 6, 2023 02:36
@vstinner

vstinner commented Sep 6, 2023

Copy link
Copy Markdown
Member Author

I was worried about Py_TRASHCAN_BEGIN_CONDITION() macro which currently calls _PyThreadState_UncheckedGet(). This macro uses private functions:

/* Python 3.9 private API, invoked by the macros below. */
PyAPI_FUNC(int) _PyTrash_begin(PyThreadState *tstate, PyObject *op);
PyAPI_FUNC(void) _PyTrash_end(PyThreadState *tstate);

/* Python 3.10 private API, invoked by the Py_TRASHCAN_BEGIN(). */
PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc);

I was worried that we still provide Python 3.9 functions. Is it the a stable ABI? Nope, these functions are not part of Misc/stable_abi.toml.

Moreover, I explicitly removed the following macros from the limited C API in Python 3.9:

  • PyTrash_UNWIND_LEVEL
  • Py_TRASHCAN_BEGIN_CONDITION()
  • Py_TRASHCAN_BEGIN()
  • Py_TRASHCAN_END()
  • Py_TRASHCAN_SAFE_BEGIN()
  • Py_TRASHCAN_SAFE_END()

So in fact, we keep Python 3.9 functions for the ABI backward compatibility, whereas we do not support these APIs in the stable ABI.

In short, it's ok to rename _PyThreadState_UncheckedGet() to PyThreadState_GetUnsafe(), it's not used by the stable ABI.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Sep 9, 2023

Copy link
Copy Markdown
Member Author

A bunch of projects currently uses _PyThreadState_UncheckedGet(), whereas I removed the function from the public C API in Python 3.13.

Affected projects (18):

  • Cython (0.29.36)
  • catboost (1.2)
  • cffi (1.15.1)
  • debugpy (1.6.7)
  • dlib (19.24.2)
  • fastobo (0.12.2)
  • frozendict (2.3.8)
  • onnx (1.14.0)
  • onnxoptimizer (0.3.13)
  • onnxsim (0.4.33)
  • orjson (3.9.1)
  • osmium (3.6.0)
  • praat-parselmouth (0.4.3)
  • ptvsd (4.3.2)
  • pybind11 (2.10.4)
  • pydevd (2.9.6)
  • pydevd-pycharm (232.8296.19)
  • pythonnet (3.0.1)

In this list, IMO the interesting one is Cython:

$ git grep -E '(_PyThreadState_UncheckedGet|__Pyx_PyThreadState_Current)'
Cython/Utility/AsyncGen.c:    tstate = __Pyx_PyThreadState_Current;
Cython/Utility/AsyncGen.c:    tstate = __Pyx_PyThreadState_Current;
Cython/Utility/Coroutine.c:    __Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue)
Cython/Utility/Coroutine.c:    tstate = __Pyx_PyThreadState_Current;
Cython/Utility/Coroutine.c:    __Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, &val);
Cython/Utility/Exceptions.c:    __pyx_assertions_enabled_flag = ! _PyInterpreterState_GetConfig(__Pyx_PyThreadState_Current->interp)->optimization_level;
Cython/Utility/Exceptions.c:#define __Pyx_PyThreadState_assign  $local_tstate_cname = __Pyx_PyThreadState_Current;
Cython/Utility/Exceptions.c:        PyThreadState *tstate = __Pyx_PyThreadState_Current;
Cython/Utility/Exceptions.c:        (void) __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line);
Cython/Utility/Exceptions.c:    PyThreadState *tstate = __Pyx_PyThreadState_Current;
Cython/Utility/ModuleSetupCode.c:    // Py3<3.5.2 does not support _PyThreadState_UncheckedGet().
Cython/Utility/ModuleSetupCode.c:  #define __Pyx_PyThreadState_Current PyThreadState_Get()
Cython/Utility/ModuleSetupCode.c:  #define __Pyx_PyThreadState_Current PyThreadState_GET()
Cython/Utility/ModuleSetupCode.c:  #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet()
Cython/Utility/ModuleSetupCode.c:  #define __Pyx_PyThreadState_Current PyThreadState_GET()
Cython/Utility/ModuleSetupCode.c:  #define __Pyx_PyThreadState_Current _PyThreadState_Current
Cython/Utility/ModuleSetupCode.c:  current = tcur == __Pyx_PyThreadState_Current;
Cython/Utility/ObjectHandling.c:    PyThreadState *tstate = __Pyx_PyThreadState_Current;
Cython/Utility/Profile.c:          tstate = __Pyx_PyThreadState_Current;                                          \
Cython/Utility/Profile.c:      PyThreadState* tstate = __Pyx_PyThreadState_Current;                                 \
Cython/Utility/Profile.c:              tstate = __Pyx_PyThreadState_Current;                                       \
Cython/Utility/Profile.c:          PyThreadState* tstate = __Pyx_PyThreadState_Current;                            \
Cython/Utility/Profile.c:      PyThreadState* tstate = __Pyx_PyThreadState_Current;                                \
Cython/Utility/Profile.c:              tstate = __Pyx_PyThreadState_Current;                                        \
Cython/Utility/Profile.c:          PyThreadState* tstate = __Pyx_PyThreadState_Current;                             \
Cython/Utility/Profile.c:      PyThreadState* tstate = __Pyx_PyThreadState_Current;                                 \

I can easily add PyThreadState_GetUnsafe() to pythoncapi-compat by calling _PyThreadState_UncheckedGet() on Python 3.12 and older. This private function is available since Python 3.5. It seems to be available on PyPy:

$ cd /usr/include/pypy3.9/
$ grep _PyThreadState_UncheckedGet -R .
./pylifecycle.h:    (_Py_IsFinalizing() ? _PyThreadState_UncheckedGet() : NULL)
./pypy_decl.h:#define _PyThreadState_UncheckedGet _PyPyThreadState_UncheckedGet
./pypy_decl.h:PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void);
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Sep 9, 2023

Copy link
Copy Markdown
Member Author

I asked in the C API Working Group which function name is better: use Unchecked suffix or Unsafe suffix?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner mentioned this pull request Sep 9, 2023
Naming convention for new C API functions capi-workgroup/problems#52
Closed
encukou
encukou reviewed Sep 11, 2023
View reviewed changes
Comment thread Doc/c-api/init.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Sep 11, 2023

Copy link
Copy Markdown
Member Author

I renamed the function to PyThreadState_GetUnchecked() and addressed @encukou's suggestion on the documentation.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

vstinner
vstinner commented Sep 18, 2023
View reviewed changes
Comment thread Doc/c-api/init.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner force-pushed the tstate_getunsafe branch from cddb3cc to 92b23e7 Compare October 3, 2023 16:12
@vstinner
pythongh-108867: Add PyThreadState_GetUnchecked() function
2372091
Add PyThreadState_GetUnchecked() function: similar to
PyThreadState_Get(), but don't issue a fatal error if it is NULL. The
caller is responsible to check if the result is NULL. Previously,
this function was private and known as _PyThreadState_UncheckedGet().
@vstinner vstinner changed the title gh-108867: Add PyThreadState_GetUnsafe() function gh-108867: Add PyThreadState_GetUnchecked() function Oct 3, 2023
@vstinner
vstinner force-pushed the tstate_getunsafe branch from 92b23e7 to 2372091 Compare October 3, 2023 16:20
@vstinner

vstinner commented Oct 3, 2023

Copy link
Copy Markdown
Member Author

I renamed the function to PyThreadState_GetUnchecked()

Oops, my PR still used PyThreadState_GetUnsafe() name. I messed up something.

Anyway, I updated it again, and now it uses PyThreadState_GetUnchecked() name everywhere.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
Link PyThreadState_Get doc to PyThreadState_GetUnchecked
48da305
@vstinner
vstinner enabled auto-merge (squash) October 3, 2023 16:23
@vstinner
vstinner merged commit d735016 into python:main Oct 3, 2023
@vstinner
vstinner deleted the tstate_getunsafe branch October 3, 2023 16:53
@bedevere-app bedevere-app Bot removed the awaiting core review label Oct 3, 2023
@vstinner

vstinner commented Oct 3, 2023

Copy link
Copy Markdown
Member Author

I added PyThreadState_GetUnchecked() to pythoncapi-compat: python/pythoncapi-compat@f78c780

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
@vstinner @Glyphack
pythongh-108867: Add PyThreadState_GetUnchecked() function (python#10…
5fd59fe
…8870)

Add PyThreadState_GetUnchecked() function: similar to
PyThreadState_Get(), but don't issue a fatal error if it is NULL. The
caller is responsible to check if the result is NULL. Previously,
this function was private and known as _PyThreadState_UncheckedGet().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@encukou encukou encukou left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@vstinner @encukou @bedevere-bot
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.