Free Threading - Initial Support #15
Merged
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.
Per discussion, this PR enables free-threading for DuckDB for 3.14t (or later).
This should be considered highly experimental, since it was tested on release candidate builds of 3.14 and without pyarrow, pandas or polars support.
Background
Python 3.14 is in RC3 with release scheduled for Oct 7, 2025.
Python 3.13 released experimental support for free-threading.
In Python 3.14 free-threaded Python is officially supported
Module State
PEP489 - multi-phase-init calls for module_state to be initialized with each interpreter*. This PR takes a half-step towards that, by consolidating global state into a single static DuckDBPyModuleState. The idea being: it's easier to manage concurrency through a single instance than across instances.
Alternative ideas: DuckDBPyModuleState is not absolutely required. The alternative is to keep the import cache/instance cache/etc and add mutexes or scoped_critical_sections to control access.
* each interpreter refers to support for subinterpreters. Multiple subinterpreters is not supported in this PR for a few reasons, primarily due to the difficulty of attaching the import_cache to all the calls that assume a single global import_cache.
scoped_critical_section
DefaultConnection is synchronized with a py::scoped_critical_section
Since cursors are not thread safe. Segfaults occur in both release & these builds when cursors are used in an unsafe manner.
Testing
A set of threading test cases are added to
tests/fast/threading. These tests should pass in both GIL enabled and free-threaded (no-GIL) builds.