Skip to content

fix(python): use pybind11 2.13.6 for CPython 3.14 allocator safety - #2108

Merged
jordimas merged 4 commits into
OpenNMT:masterfrom
cepeter:fix/py314-pybind11-type-doc-allocator
Oct 10, 2026
Merged

jordimas merged 4 commits into
OpenNMT:masterfrom
cepeter:fix/py314-pybind11-type-doc-allocator

Conversation

@cepeter

@cepeter cepeter commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #2107.

Problem

Published CPython 3.14 CTranslate2 4.8.2 wheels import successfully, then abort during interpreter finalization under the debug allocator:

Fatal Python error: _PyMem_DebugRawFree: bad ID: Allocated using API 'o', verified using API 'm'
Python runtime state: finalizing

GDB confirms type_dealloc -> PyMem_Free(type->tp_doc). The current wheel's pinned pybind11 2.11.1 allocates tp_doc via PyObject_MALLOC (object domain), while CPython 3.13+ frees it with PyMem_Free (memory domain). Python 3.11's different allocator API in type_dealloc explains the earlier absence of the crash.

Changes

  • Bump pybind11 2.11.1 → 2.13.6 in both Python build-system requirements and cibuildwheel's python/install_requirements.txt to guarantee both build routes use the fixed allocation behavior.
  • Add a Linux CPython 3.14 wheel validation job that installs the actual wheel produced by cibuildwheel and requires clean exit from python -X dev -W error::ResourceWarning -c 'import ctranslate2', not merely successful import.
  • Include the new job in the publishing dependencies, preventing regressions from being published.

Independently validated fix

On the official CPython 3.14.8 GitHub runner, a minimal C++ heap type with docstrings using pybind11 2.11.1 reproduces exit 134, while 2.13.6 and 3.0.1 exit 0: isolated comparison.

Most importantly, a complete CTranslate2 v4.8.2 Python extension was rebuilt from immutable upstream source commit d44d2d069eb88c7b7804da864c10c201501cb4a9, with pybind11 2.13.6 and the original official native inference core library:

  • python -X dev -W error::ResourceWarning -c 'import ctranslate2, faster_whisper' exited 0; provenance assertion verified the rebuilt extension was loaded.
  • Three synthetic Python 3.14 native/voice tests, including WAV decoding, passed.
  • Successful full binding rebuild & test.

The experiments did not publish or replace wheels. This PR fixes the upstream build inputs and enforces the result on future release artifacts. No model files, credentials, or user data are required.

Distinguish the cp314 ABI from cp314t when both release artifacts exist.
Keep the exactly-one wheel check and debug-allocator shutdown gate.

Verified filename-only probes for coexistence, missing, and duplicate wheels.
@jordimas

Copy link
Copy Markdown
Collaborator

Thanks so much!

@jordimas
jordimas merged commit f2f54b4 into OpenNMT:master Oct 10, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python 3.14 exit abort: pybind11 2.11.1 tp_doc PyObject_MALLOC mismatches CPython PyMem_Free

2 participants