From d930e122854358d99220a980e6a27382c22ad9a5 Mon Sep 17 00:00:00 2001 From: crusaderky Date: Wed, 17 Dec 2025 09:18:22 +0000 Subject: [PATCH 1/4] pixi builds for free-threading and tsan --- Tools/pixi-packages/README.md | 8 ++- Tools/pixi-packages/build.sh | 12 +++- Tools/pixi-packages/free-threading/pixi.toml | 8 +++ .../pixi-packages/free-threading/recipe.yaml | 63 +++++++++++++++++++ Tools/pixi-packages/tsan/pixi.toml | 8 +++ Tools/pixi-packages/tsan/recipe.yaml | 63 +++++++++++++++++++ 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 Tools/pixi-packages/free-threading/pixi.toml create mode 100644 Tools/pixi-packages/free-threading/recipe.yaml create mode 100644 Tools/pixi-packages/tsan/pixi.toml create mode 100644 Tools/pixi-packages/tsan/recipe.yaml diff --git a/Tools/pixi-packages/README.md b/Tools/pixi-packages/README.md index 50c3315ac0e5fc..049f38b06b93d0 100644 --- a/Tools/pixi-packages/README.md +++ b/Tools/pixi-packages/README.md @@ -12,7 +12,7 @@ python = { git = "https://github.com/python/cpython", subdirectory = "Tools/pixi ``` This is particularly useful when developers need to build CPython from source -(for example, for an ASan-instrumented build), as it does not require any manual +(for example, for an ASan or TSan-instrumented build), as it does not require any manual clone or build steps. Instead, Pixi will automatically handle both the build and installation of the package. @@ -20,7 +20,9 @@ Each package definition is contained in a subdirectory, but they share the build `build.sh` in this directory. Currently defined package variants: - `default` -- `asan`: ASan-instrumented build with `PYTHON_ASAN=1` +- `free-threading` +- `asan`: ASan-instrumented build +- `tsan`: free-threading, TSan-instrumented build ## Maintenance @@ -30,7 +32,7 @@ Each package definition is contained in a subdirectory, but they share the build ## Opportunities for future improvement -- More package variants (such as TSan, UBSan) +- More package variants (such as UBSan) - Support for Windows - Using a single `pixi.toml` and `recipe.yaml` for all package variants is blocked on https://github.com/prefix-dev/pixi/issues/4599 - A workaround can be removed from the build script once https://github.com/prefix-dev/rattler-build/issues/2012 is resolved diff --git a/Tools/pixi-packages/build.sh b/Tools/pixi-packages/build.sh index 120f1d6bb0088a..6fe9b4ba50c662 100644 --- a/Tools/pixi-packages/build.sh +++ b/Tools/pixi-packages/build.sh @@ -1,11 +1,19 @@ #!/bin/bash -if [[ "${PYTHON_VARIANT}" == "asan" ]]; then +if [[ "${PYTHON_VARIANT}" == "free-threading" ]]; then + echo "BUILD TYPE: FREE-THREADING" + BUILD_DIR="../build_free_threading" + CONFIGURE_EXTRA="--disable-gil" +elif [[ "${PYTHON_VARIANT}" == "asan" ]]; then echo "BUILD TYPE: ASAN" BUILD_DIR="../build_asan" CONFIGURE_EXTRA="--with-address-sanitizer" - export PYTHON_ASAN="1" export ASAN_OPTIONS="strict_init_order=true" +elif [[ "${PYTHON_VARIANT}" == "tsan" ]]; then + echo "BUILD TYPE: TSAN" + BUILD_DIR="../build_tsan" + CONFIGURE_EXTRA="--disable-gil --with-thread-sanitizer" + export TSAN_OPTIONS="suppressions=${SRC_DIR}/Tools/tsan/suppressions_free_threading.txt" else echo "BUILD TYPE: DEFAULT" BUILD_DIR="../build" diff --git a/Tools/pixi-packages/free-threading/pixi.toml b/Tools/pixi-packages/free-threading/pixi.toml new file mode 100644 index 00000000000000..001ff78fa5d8cb --- /dev/null +++ b/Tools/pixi-packages/free-threading/pixi.toml @@ -0,0 +1,8 @@ +[workspace] +channels = ["https://prefix.dev/conda-forge"] +platforms = ["osx-arm64", "linux-64"] +preview = ["pixi-build"] + +[package.build.backend] +name = "pixi-build-rattler-build" +version = "*" diff --git a/Tools/pixi-packages/free-threading/recipe.yaml b/Tools/pixi-packages/free-threading/recipe.yaml new file mode 100644 index 00000000000000..61c01562d35519 --- /dev/null +++ b/Tools/pixi-packages/free-threading/recipe.yaml @@ -0,0 +1,63 @@ +context: + # Keep up to date + version: "3.15" + +package: + name: python + version: ${{ version }} + +source: + - path: ../../.. + +build: + files: + exclude: + - "*.o" + script: + file: ../build.sh + env: + PYTHON_VARIANT: "free-threading" + +# derived from https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml +requirements: + build: + - ${{ compiler('c') }} + - ${{ compiler('cxx') }} + - make + - pkg-config + # configure script looks for llvm-ar for lto + - if: osx + then: + - llvm-tools + - if: linux + then: + - ld_impl_${{ target_platform }} + - binutils_impl_${{ target_platform }} + - clang-19 + - llvm-tools-19 + + host: + - bzip2 + - sqlite + - liblzma-devel + - zlib + - zstd + - openssl + - readline + - tk + # These two are just to get the headers needed for tk.h, but is unused + - xorg-libx11 + - xorg-xorgproto + - ncurses + - libffi + - if: linux + then: + - ld_impl_${{ target_platform }} + - libuuid + - libmpdec-devel + - expat + +about: + homepage: https://www.python.org/ + license: Python-2.0 + license_file: LICENSE diff --git a/Tools/pixi-packages/tsan/pixi.toml b/Tools/pixi-packages/tsan/pixi.toml new file mode 100644 index 00000000000000..001ff78fa5d8cb --- /dev/null +++ b/Tools/pixi-packages/tsan/pixi.toml @@ -0,0 +1,8 @@ +[workspace] +channels = ["https://prefix.dev/conda-forge"] +platforms = ["osx-arm64", "linux-64"] +preview = ["pixi-build"] + +[package.build.backend] +name = "pixi-build-rattler-build" +version = "*" diff --git a/Tools/pixi-packages/tsan/recipe.yaml b/Tools/pixi-packages/tsan/recipe.yaml new file mode 100644 index 00000000000000..f036cac180d22f --- /dev/null +++ b/Tools/pixi-packages/tsan/recipe.yaml @@ -0,0 +1,63 @@ +context: + # Keep up to date + version: "3.15" + +package: + name: python + version: ${{ version }} + +source: + - path: ../../.. + +build: + files: + exclude: + - "*.o" + script: + file: ../build.sh + env: + PYTHON_VARIANT: "tsan" + +# derived from https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml +requirements: + build: + - ${{ compiler('c') }} + - ${{ compiler('cxx') }} + - make + - pkg-config + # configure script looks for llvm-ar for lto + - if: osx + then: + - llvm-tools + - if: linux + then: + - ld_impl_${{ target_platform }} + - binutils_impl_${{ target_platform }} + - clang-19 + - llvm-tools-19 + + host: + - bzip2 + - sqlite + - liblzma-devel + - zlib + - zstd + - openssl + - readline + - tk + # These two are just to get the headers needed for tk.h, but is unused + - xorg-libx11 + - xorg-xorgproto + - ncurses + - libffi + - if: linux + then: + - ld_impl_${{ target_platform }} + - libuuid + - libmpdec-devel + - expat + +about: + homepage: https://www.python.org/ + license: Python-2.0 + license_file: LICENSE From 57d45b97a63eff8e14287f8ff01ffa41641a52fa Mon Sep 17 00:00:00 2001 From: crusaderky Date: Fri, 2 Jan 2026 15:25:13 +0000 Subject: [PATCH 2/4] Rename to tsan-free-threading --- Tools/pixi-packages/README.md | 2 +- Tools/pixi-packages/build.sh | 6 +++--- Tools/pixi-packages/{tsan => tsan-free-threading}/pixi.toml | 0 .../pixi-packages/{tsan => tsan-free-threading}/recipe.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename Tools/pixi-packages/{tsan => tsan-free-threading}/pixi.toml (100%) rename Tools/pixi-packages/{tsan => tsan-free-threading}/recipe.yaml (96%) diff --git a/Tools/pixi-packages/README.md b/Tools/pixi-packages/README.md index 049f38b06b93d0..c5fc4a1af15c21 100644 --- a/Tools/pixi-packages/README.md +++ b/Tools/pixi-packages/README.md @@ -22,7 +22,7 @@ Each package definition is contained in a subdirectory, but they share the build - `default` - `free-threading` - `asan`: ASan-instrumented build -- `tsan`: free-threading, TSan-instrumented build +- `tsan-free-threading`: TSan-instrumented free-threading build ## Maintenance diff --git a/Tools/pixi-packages/build.sh b/Tools/pixi-packages/build.sh index 6fe9b4ba50c662..b2bceda779f2cc 100644 --- a/Tools/pixi-packages/build.sh +++ b/Tools/pixi-packages/build.sh @@ -9,9 +9,9 @@ elif [[ "${PYTHON_VARIANT}" == "asan" ]]; then BUILD_DIR="../build_asan" CONFIGURE_EXTRA="--with-address-sanitizer" export ASAN_OPTIONS="strict_init_order=true" -elif [[ "${PYTHON_VARIANT}" == "tsan" ]]; then - echo "BUILD TYPE: TSAN" - BUILD_DIR="../build_tsan" +elif [[ "${PYTHON_VARIANT}" == "tsan-free-threading" ]]; then + echo "BUILD TYPE: TSAN FREE-THREADING" + BUILD_DIR="../build_tsan_free_threading" CONFIGURE_EXTRA="--disable-gil --with-thread-sanitizer" export TSAN_OPTIONS="suppressions=${SRC_DIR}/Tools/tsan/suppressions_free_threading.txt" else diff --git a/Tools/pixi-packages/tsan/pixi.toml b/Tools/pixi-packages/tsan-free-threading/pixi.toml similarity index 100% rename from Tools/pixi-packages/tsan/pixi.toml rename to Tools/pixi-packages/tsan-free-threading/pixi.toml diff --git a/Tools/pixi-packages/tsan/recipe.yaml b/Tools/pixi-packages/tsan-free-threading/recipe.yaml similarity index 96% rename from Tools/pixi-packages/tsan/recipe.yaml rename to Tools/pixi-packages/tsan-free-threading/recipe.yaml index f036cac180d22f..dfae06ad7a51d5 100644 --- a/Tools/pixi-packages/tsan/recipe.yaml +++ b/Tools/pixi-packages/tsan-free-threading/recipe.yaml @@ -16,7 +16,7 @@ build: script: file: ../build.sh env: - PYTHON_VARIANT: "tsan" + PYTHON_VARIANT: "tsan-free-threading" # derived from https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml requirements: From 5ff29b41afa3d0f56035600ee901d325a093ee12 Mon Sep 17 00:00:00 2001 From: crusaderky Date: Fri, 2 Jan 2026 15:25:27 +0000 Subject: [PATCH 3/4] Add libclang_rt hack --- Tools/pixi-packages/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tools/pixi-packages/build.sh b/Tools/pixi-packages/build.sh index b2bceda779f2cc..8926de2603846f 100644 --- a/Tools/pixi-packages/build.sh +++ b/Tools/pixi-packages/build.sh @@ -41,5 +41,6 @@ ln -sf "${PREFIX}/bin/python3" "${PREFIX}/bin/python" # https://github.com/prefix-dev/rattler-build/issues/2012 if [[ ${OSTYPE} == "darwin"* ]]; then - cp "${BUILD_PREFIX}/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" "${PREFIX}/lib/libclang_rt.asan_osx_dynamic.dylib" + cp "${BUILD_PREFIX}/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" "${PREFIX}/lib/" + cp "${BUILD_PREFIX}/lib/clang/21/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib" "${PREFIX}/lib/" fi From 9a2a8963286077536f67b89a2123355aeb049a3d Mon Sep 17 00:00:00 2001 From: crusaderky Date: Fri, 2 Jan 2026 16:02:29 +0000 Subject: [PATCH 4/4] Add troubleshooting for tsan --- Tools/pixi-packages/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Tools/pixi-packages/README.md b/Tools/pixi-packages/README.md index c5fc4a1af15c21..94d606cee3439d 100644 --- a/Tools/pixi-packages/README.md +++ b/Tools/pixi-packages/README.md @@ -36,3 +36,18 @@ Each package definition is contained in a subdirectory, but they share the build - Support for Windows - Using a single `pixi.toml` and `recipe.yaml` for all package variants is blocked on https://github.com/prefix-dev/pixi/issues/4599 - A workaround can be removed from the build script once https://github.com/prefix-dev/rattler-build/issues/2012 is resolved + +## Troubleshooting + +TSan builds may crash on Linux with +``` +FATAL: ThreadSanitizer: unexpected memory mapping 0x7977bd072000-0x7977bd500000 +``` +To fix it, try reducing `mmap_rnd_bits`: + +```bash +$ sudo sysctl vm.mmap_rnd_bits +vm.mmap_rnd_bits = 32 # too high for TSan +$ sudo sysctl vm.mmap_rnd_bits=28 # reduce it +vm.mmap_rnd_bits = 28 +```