Skip to content

Proper free-threaded ABI support blockers #126

Closed

Description

@nitzmahone

Tracking known blockers to actual support of Python's new t free-threaded ABI - add new ones as we discover them.

  • Extensions built with Py_LIMITED_API (default) under t ABI will always segfault. (fixed by Hard disable Py_LIMITED_API under free-threaded build #125)
  • Threaded embedding tests fail under free-threaded build. ([Python bug]
    (Crash in Py_Initialize in non-main thread in free-threading build python/cpython#123022), fixed in 3.13.0rc2)
  • Add non-artifact CI job for 3.13t.
  • Evaluate all type creation/caching code for obvious GIL-incidental locking or deadlock issues sans GIL.
  • Evaluate all manual refcounting, buffer manipulations, marshaling code, etc for obvious concurrency issues.
  • Build a lot more threaded stress tests for the above, measure coverage.
  • Update documentation to describe current state, concerns around GIL-free operation modes.
  • Once we have some confidence in true GIL-free operations, provide a high-level opt-in/out for CFFI-backed extensions to call PyUnstable_Module_SetGIL() during extension init to control the automatic legacy extension GIL re-enable.
  • Clean up and enable at least optional runs of the full test suite under Windows (skipped in CI for time, currently numerous broken tests and at least one item deadlocks under the parallel runner).
  • Remove known dead code from active development branches (ala Remove pre-Python 3.8 C code #124).
  • Work with high-profile CFFI-consuming projects (e.g. cryptography, pynacl, pygame, ?) to ensure any future threaded stress tests are not broken by CFFI issues.

Activity

  1. changed the title [-]Proper free-threaded API support blockers[/-] [+]Proper free-threaded ABI support blockers[/+] on Sep 6, 2024
  2. colesbury commented on Nov 2, 2024

    @colesbury
    Contributor

    Hi @nitzmahone - I'm happy to help out with this if you're okay with reviewing some PRs.

  3. HeHongyeFY commented on Dec 24, 2024

    @HeHongyeFY

    what's the expect time this issue the can be close?
    Is there plan?

  4. ofek commented on Mar 4, 2025

    @ofek
    Contributor

    Is there anything concrete that contributors can assist with here?

  5. ofek commented on Mar 4, 2025

    @ofek
    Contributor

    It looks like the work is happening over here Quansight-Labs#1

  6. ngoldbaum commented on Jun 17, 2025

    @ngoldbaum
    Contributor

    Hi @arigo @nitzmahone. As an update, after a lot of hard work, we think we've fixed the thread safety issues in the CFFI implementation and we're currently planning to publish a fork of CFFI named CFFI-ft that exports a cffi_ft module. See Quansight-Labs#16.

    This will allow @hynek to publish argon2-cffi-bindings wheels that support the free-threaded build, allowing pip install jupyter to successfully complete on the free-threaded interpreter out of the box. See hynek/argon2-cffi-bindings#67 (comment).

    Our hope is that the fork is short-lived and we'd like to upstream the changes ASAP. You can see what the changes look like here: main...Quansight-Labs:cffi-ft:c053f17.

    The diff I linked to doesn't include subsequent changes to rename the project and modules. It still needs to be cleaned up a little to be upstreamed and a decent fraction of the change is CI configuration. I'd say the full "real" C diff is about 1000 LoC.

    The testing is based on the existing CI configuration, with cp313t added to the testing matrix on all platforms. We also set up new macos-latest, windows-latest, and ubuntu-latest CI runs that that run the tests using pytest-run-parallel - a pytest plugin that batch-runs tests from an existing test suite in a thread pool to trigger thread safety issues due to use of global state in the implementation. We also set up a similar CI run using the cpython_sanity docker images running a thread sanitizer-instrumented CPython and CFFI build.

    The code supports cp313t and the current beta cp314t, with CI enabled on all platforms for cp313t and the Linux TSAN build running on cp314t to avoid triggering known races in CPython that have been fixed in 3.14. While we've added a suppression file for some races in CPython that still happen under 3.14, our implementation does not trigger any races under TSAN inside CFFI in our testing.

    We've also manually tested both argon2-cffi and pynacl using pytest-run-parallel and TSAN and have not seen any race reports on either an ARM Mac or on the x86 Linux docker image. The argon2-cffi tests also include an explicitly multithreaded test that doesn't trigger any races.

    We're doing the fork both to fix a common annoyance users hit when they set up an environment and to get real-world testing of our code. We're happy to deal with teething issues or have any free-threading related bugs or feature requests directed to our fork.

    On the other hand, this approach does impose real costs on users of CFFI who would like to experiment with free-threading. It also forces those users to depend on CFFI-ft for all Python 3.13 and newer builds due to limitations of the current environment marker standard. To mitigate that, would you prefer we don't do the temporary fork and instead open a PR with our changes for you to review right now? Or do you agree that forking is a reasonable way for us to test this without putting a lot of burden on you and the broader CFFI ecosystem and give you confidence in our changes? Ultimately we want to upstream the changes in a manner that makes you feel the most comfortable.

  7. arigo commented on Jun 17, 2025

    @arigo
    Contributor

    Hi Nathan,

    I can immediately see places that are not safe (as far as I understand it, so I may be wrong) but aren't mentioned in the diff---for example, any usage of unique_cache in _cffi_backend.c. But that's besides the point I want to make: cffi is at this point a bit moribund, and even reviewing 1000 lines of diff to make sure there is no new subtle bug in the non-freethreading case is more than I can promise. So I think that the best approach is to start and manage your own fork.

  8. ngoldbaum commented on Jun 17, 2025

    @ngoldbaum
    Contributor

    for example, any usage of unique_cache in _cffi_backend.c

    See the LOCK_UNIQUE_CACHE() and UNLOCK_UNIQUE_CACHE() macros - there's a global lock that prevents concurrent access. There's no locking during the module initialization because the interpreter holds a per-module lock during import.

    If you have more places you think we should look I'd love to hear about that.

    So I think that the best approach is to start and manage your own fork.

    OK - hopefully after we have some more real-world testing we can try again.

  9. colesbury commented on Jun 17, 2025

    @colesbury
  10. arigo commented on Jun 17, 2025

    @arigo
    Contributor

    Oh yes, sorry about that. I think github gave me a very partial view of the diff of _cffi_backend.c for some reason.

  11. nitzmahone commented on Jun 18, 2025

    @nitzmahone
    MemberAuthor

    First, huge props to the folks at Quansight and everyone else that's taken this on- thank you!

    I'll preface my opinion on "how should upstream CFFI handle this change?" with the note that I'm not entirely sure whose decision it will/should ultimately be. I'm in the odd position of "reluctant maintainer-ish" of a project for which I'm not a direct consumer (Ansible uses cryptography, which needs CFFI). Faced with the prospect of CFFI moving to source-only releases, I've taken on packaging and maintenance duties to keep things working and easily installable. My motives were both to give back, but also to stem the inevitable tide of "I can't pip install Ansible!" that would surely follow if CFFI required everyone to build it locally. While I've got plenty of experience building highly concurrent multi-(language|arch|platform) software like CFFI, I'm by no means an expert on the nuances of CFFI itself, and don't currently have the bandwidth to become one to the level that a "proper" review of this change set requires.

    That said, I'm +1 for bringing these changes upstream. At first blush, I don't see a lot of risk to existing non-FT usage introduced by these changes. If a more thorough review (which I'll make time for!) bears that out, at worst, FT-flavored extensions could still encounter deadlocks, races requiring synchronization, or other failures in some feature areas, but are on the whole better off than without these changes. Issues can always be fixed. I'd probably want to put some "experimental" caution tape around it in the docs for awhile, but FT appears to be here to stay, so IMO the project should support it. I don't think anyone is served by long-term existence of a fork unless that fork wants to go in a direction that the upstream does not.

    The bigger question is really around the project governance limbo- while I will make the call myself if necessary, I feel like the janitor hanging around after-hours with a set of keys being asked to approve changes to the building's electrical system, so I'd be more comfortable with explicit +1's or "don't cares" from some other folks with stakes/interest in this thing (@arigo, @mattip, others?).

  12. mattip commented on Jun 18, 2025

    @mattip
    Contributor

    Thanks for picking up the challenge. I lost my maintainer role in the move to github, but would be willing to rejoin as a maintainer to share the burden.

  13. nitzmahone commented on Jun 18, 2025

    @nitzmahone
    MemberAuthor

    would be willing to rejoin as a maintainer to share the burden.

    @mattip with a +1 (or a few days of silence 😉 ) from @arigo, I'd very much welcome that!

  14. mattip commented on Jun 18, 2025

    @mattip
    Contributor

    If not clear, I am +1 on getting FT into CFFI

  15. nitzmahone commented on Jun 18, 2025

    @nitzmahone
    MemberAuthor

    would you prefer we don't do the temporary fork and instead open a PR

    @ngoldbaum I'm +1 for "file the upstream PR now". Assuming nobody finds anything super-objectionable, would a CFFI 1.18.0 prerelease within the next ~ couple weeks meet the needs for your dependency concerns (at least enough to forgo publishing the fork)? e.g., listing a cffi~=1.18.0b1 dep (possibly with FT env marker - can't recall how that discussion turned out)

  16. ngoldbaum commented on Jun 18, 2025

    @ngoldbaum
    Contributor

    I think that's very reasonable. I'll try to tidy the diff a little and propose an upstream PR ASAP.

  17. ofek commented on Jun 18, 2025

    @ofek
    Contributor

    In the coming years free-threaded will become the default so I was worried about a required-in-practice fork. I very much appreciate everyone coming together on this!

  18. arigo commented on Jun 19, 2025

    @arigo
    Contributor

    Yes, +1 on giving @mattip the maintainer role again, or full admin if he wants it. My thanks to Matti and to Matt for their time, and to the team behind Nathan for pushing this forward!

  19. nitzmahone commented on Jun 19, 2025

    @nitzmahone
    MemberAuthor

    @mattip you've got mail 😉

  20. ngoldbaum commented on Jun 19, 2025

    @ngoldbaum
    Contributor

    I'll try to tidy the diff a little and propose an upstream PR ASAP.

    See #178

  21. ngoldbaum commented on Jul 23, 2025

    @ngoldbaum
    Contributor

    Assuming nobody finds anything super-objectionable, would a CFFI 1.18.0 prerelease within the next ~ couple weeks meet the needs for your dependency concerns (at least enough to forgo publishing the fork)? e.g., listing a cffi~=1.18.0b1 dep (possibly with FT env marker - can't recall how that discussion turned out)

    A little over a month later - I think everything is ready. We're now thinking that this is going to be a CFFI 2.0 release and #178 sets that all up.

    Is there any chance we can get some signal from @nitzmahone or @arigo that what I quoted above is still the plan, and @mattip can go ahead with merging #178 and preparing a CFFI 2.0 release shipping free-threaded support and 3.14 support?

    3.14rc1 came out yesterday and the free-threaded build is no longer considered experimental in 3.14, so this is starting to get a little more acute. cibuildwheel will also enable free-threaded builds by default starting in 3.14: pypa/cibuildwheel#2503

  22. nitzmahone commented on Jul 25, 2025

    @nitzmahone
    MemberAuthor

    Is there any chance we can get some signal from @nitzmahone or @arigo that what I quoted above is still the plan

    Just to close the loop here for anyone that's not watching the fun over on #178- yep! Some late-breaking 3.13t issues to diagnose (and hopefully fix), but IMO as soon as that's resolved, CFFI 2.0.0b1 can immediately follow.

  23. ngoldbaum commented on Aug 6, 2025

    @ngoldbaum
    Contributor

    pyca/cryptography#12555 and pyca/pynacl#880 are now fully green and ready to go whenever CFFI 2.0.0 final is released.

  24. mattip commented on Sep 9, 2025

    @mattip
    Contributor

    Can we close this?

  25. mattip commented on Feb 4, 2026

    @mattip
    Contributor

    Closing, please open new issues if problems with free-threaded python are detected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions