Skip to content

gh-146636: Add Free-threaded Stable ABI migration guide - #148453

Closed
clin1234 wants to merge 18 commits into
python:mainfrom
clin1234:patch-6
Closed

gh-146636: Add Free-threaded Stable ABI migration guide#148453
clin1234 wants to merge 18 commits into
python:mainfrom
clin1234:patch-6

Conversation

@clin1234

@clin1234clin1234 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

@da-woodsda-woods left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot that isn't right here (or is mostly about freethreading generally rather than about the stable ABI).

Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
:c:func:`PyDict_SetItem`, or explicitly using macros), it attempts to acquire
the underlying mutex.

Using Critical Sections

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weakness right now is that I don't think they're part of the stable ABI (but hopefully will be)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you were referring to https://docs.python.org/3/c-api/dict.html#c.PyDict_SetItem, it's part of the Stable ABI: https://docs.python.org/3/c-api/dict.html#c.PyDict_SetItem

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - I was referring to critical sections. Which I really hope are added before 3.15 comes out but I don't think currently are. Sorry if that was ambiguous.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now being proposed: #149225

Comment threadDoc/howto/freethreading-stable-abi.rst Outdated
@da-woods

Copy link
Copy Markdown
Contributor

I think the way most people will want to proceed is:

  1. Switch to PEP 793 module initialization (https://peps.python.org/pep-0793/). This will hopefully be a fairly trivial change for most people.
  2. Switch to using opaque objects and accessing all their type data through PyObject_GetTypeData. This will be a painful change for most people (and especially if they're starting from static types).
  3. Follow the general free-threading C API advice in https://docs.python.org/3/howto/free-threading-extensions.html#container-thread-safety (e.g. avoid borrowed reference, use critical sections once they become available). My personal opinion is that it isn't worth duplicating the advice.
  4. Decide if they want to mark their extension as thread-safe.

But steps 1 and 2 are the main ones and are almost not covered here.

Comment threadDoc/howto/freethreading-stable-abi.rst
@clin1234

clin1234 commented Apr 12, 2026

Copy link
Copy Markdown
ContributorAuthor

Based on WIP PR: #148013

@picnixz

Copy link
Copy Markdown
Member

I don't understand why we are having this PR when the reference documentation is not merged. Can we revisit this later? I would have expected the PEP's author to write this.

@picnixz
picnixz marked this pull request as draft April 12, 2026 17:03
@clin1234
clin1234 marked this pull request as ready for review April 12, 2026 17:44
@picnixz

Copy link
Copy Markdown
Member

I left it as a draft because I do not think it is time for it to be reviewed. Please wait for the PEP author first.

@encukou

Copy link
Copy Markdown
Member

Please don't repeat text from free-threading HOWTO. This document should be about migrating from that to the stable ABI; anything that's relevant to free-threading in general should be explained there (and possibly linked from the new document).

Also don't repeat information from the reference docs. A migration guide should link to the docs, and perhaps point out how/why the new thing is different.

And please see here on how-to guides in general: https://diataxis.fr/how-to-guides/

@read-the-docs-community

read-the-docs-communityBot commented May 2, 2026

Copy link
Copy Markdown

@clin1234
clin1234 requested a review from da-woodsMay 7, 2026 19:31
@clin1234
clin1234 marked this pull request as draft May 7, 2026 19:31
@clin1234
clin1234 marked this pull request as ready for review May 17, 2026 09:33
This document provides detailed instructions on how to use the Free Threading Stable ABI in CPython, including guidelines for module initialization, API usage, and thread safety considerations.
Clarified access restrictions on PyObject members and recommended functions for type and reference count manipulation.
clin1234and others added 9 commits May 17, 2026 05:33
Clarified that direct access to PyObject members is prohibited.
Co-authored-by: da-woods <dw-git@d-woods.co.uk>
Updated documentation to clarify the identification of free-threaded limited API builds in C, including changes to macros and initialization methods.
Updated the documentation to clarify the use of the stable ABI and GIL management in Python extensions, including changes to member access and initialization methods.
Removed sections on API guidelines, critical sections, and thread safety from the documentation.
Comment on lines +17 to +18
The CPython C API exposes the :c:macro:`!Py_LIMITED_API` macro: in the free-threaded stable ABI
build it's defined to ``1``, and in the regular build it's not defined.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't right.

Comment on lines +28 to +32
- define both :c:macro:`!Py_LIMITED_API` and :c:macro:`!Py_TARGET_ABI3T`, or
- define only :c:macro:`!Py_LIMITED_API` and:

- on Windows, define :c:macro:`!Py_GIL_DISABLED`;
- on other systems, use the headers of free-threaded build of Python.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idiomatic way is probably just to define Py_TARGET_ABI3T with the version hex that you want to target.

The other ways (involving defining Py_LIMITED_API and maybe using the free-threading headers) are a bit opaque so it's probably better not to recommend them.

Comment on lines +37 to +38
Accessing any member of ``PyObject`` directly is now prohibited, like the non-GIL
stable ABI. For instance, prefer ``Py_TYPE()`` and ``Py_SET_TYPE()`` over ``ob_type``,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like the non-GIL stable ABI

I think this is the wrong way around and it's "the GIL stable ABI".

I think also that accessing the members is recommended against in the GIL stable ABI and actually impossible in the freethreading stable ABI.

the GIL disabled; otherwise importing the extension will raise a warning and
enable the GIL at runtime.

Multi-phase and single-phase initialization is supported to indicate that an extension module

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think single-phase initialization is supported

PySlot_END
};

Furthermore, using ``PyABIInfo_VAR`` and ``Py_mod_abi`` is recommended so that an

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

required I think


.. _critical-sections:

Replacements:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least in the C and C++ world the macros are available and encouraged. So I'm not sure "replacements" makes sense.

Comment on lines +119 to +124
|:c:macro:`Py_BEGIN_CRITICAL_SECTION_MUTEX` |``PyCriticalSection_BeginMutex`` |
|:c:macro:`Py_END_CRITICAL_SECTION` |``PyCriticalSection_End`` |
+-------------------------------------------+---------------------------------------+
|:c:macro:`Py_BEGIN_CRITICAL_SECTION2_MUTEX`|``PyCriticalSection2_BeginMutex`` |
|:c:macro:`Py_END_CRITICAL_SECTION2` |``PyCriticalSection2_End`` |
+-------------------------------------------+---------------------------------------+

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the mutex versions are exposed at all

``Py_REFCNT``, ``Py_IncRef()`` and ``Py_DecRef()`` over ``ob_refcnt``, etc.

Similarly, members of ``PyVarObject`` are not visible. If you need any object of such type
to be passed as a ``PyObject`` parameter to any API function, cast it directly as ``PyObject``.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The big consequence here is not that you can't access the members. It's that you can't define structures like

struct S {
PyObject_HEAD
// your struct goes here
};

and thus have to omit the PyObject_HEAD and set the object size to -size to indicate opaqueness.

You also can't use PyVarObject at all easily right now.

@encukou

Copy link
Copy Markdown
Member

Thank you @clin1234. I'll take it from here.

@clin1234

Copy link
Copy Markdown
ContributorAuthor

Thank you @clin1234. I'll take it from here.

Any other major PRs as part of implementing PEP 803 that should be mentioned in the Migration Guide?

@encukou

Copy link
Copy Markdown
Member

Continued in #150580.

Any other major PRs as part of implementing PEP 803 that should be mentioned in the Migration Guide?

Mentions should go in Release notes; a guide should rather be full of practical advice.
All the PRs should be attached to #146636 though.

@encukouencukou closed this May 29, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting reviewDO-NOT-MERGEdocsDocumentation in the Doc dirskip news

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants

@clin1234@da-woods@picnixz@encukou