Skip to content

fix(treespec): avoid casts during interpreter finalization - #294

Merged
XuehaiPan merged 1 commit into
metaopt:mainfrom
XuehaiPan:codex/fix-subinterpreter-finalization
Aug 21, 2026
Merged

fix(treespec): avoid casts during interpreter finalization#294
XuehaiPan merged 1 commit into
metaopt:mainfrom
XuehaiPan:codex/fix-subinterpreter-finalization

Conversation

@XuehaiPan

Copy link
Copy Markdown
Member

Description

Avoid registry-dependent py::cast calls from the PyTreeSpec and PyTreeIter garbage-collection slots. The slots now access the constructed C++ value directly from the pybind11 instance wrapper, and the fix is documented in the changelog.

Motivation and Context

The CPython 3.14t ppc64le job in release run 32338078331 aborted during Py_EndInterpreter(). A tp_traverse or tp_clear slot called py::cast after pybind11's interpreter-local type metadata became unavailable, causing a pybind11::cast_error to escape the C callback and terminate the process.

Garbage-collection slots must remain usable throughout interpreter teardown and must not depend on registry state that may already have been finalized. The separate CPython 3.15t s390x concurrent-import failure occurs inside pybind11 before optree module initialization and is not addressed here.

  • I have raised an issue to propose this change (required for new features and bug fixes)

Types of changes

What types of changes does your code introduce? Put an x in all the boxes that apply:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds core functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (update in the documentation)

Implemented Tasks

  • Remove registry-dependent casts from the PyTreeSpec GC slots.
  • Apply the same lifetime-safe access to the PyTreeIter GC slots while preserving the unconstructed-holder guard.
  • Document the fix in the unreleased changelog.

Checklist

Go over all the following points, and put an x in all the boxes that apply.
If you are unsure about any of these, don't hesitate to ask. We are here to help!

  • I have read the CONTRIBUTION guide. (required)
  • My change requires a change to the documentation.
  • The existing test_type_cache_cleanup_across_subinterpreters regression test covers this bug.
  • I have updated the documentation accordingly.
  • I have reformatted the code using the repository formatting hooks. (required)
  • I have checked the code using the repository lint hooks. (required)
  • I have ensured make test passes. (required)

Validation

  • make test: 93,894 passed, 26 skipped, 1 xfailed; 100% coverage.
  • python3 -m pre_commit run --all-files: passed.
  • The exact CPython 3.14t ppc64le environment is available only in CI and still requires remote confirmation.
  • clang-tidy --fix was not run on macOS.

Read PyTreeSpec and PyTreeIter values directly from constructed pybind11 instances in their garbage-collection slots. This avoids interpreter-local type lookups after pybind11 metadata becomes unavailable, where an escaping cast error would terminate the process.

Update the unreleased changelog.
@XuehaiPan
XuehaiPan marked this pull request as ready for review August 20, 2026 12:01
@XuehaiPan XuehaiPan added enhancement New feature or request cxx Something related to the CXX source code labels Aug 20, 2026
@XuehaiPan XuehaiPan self-assigned this Aug 20, 2026
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (6b2a48f) to head (84f432d).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #294   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           15        15           
  Lines         1655      1655           
  Branches       225       225           
=========================================
  Hits          1655      1655           
Flag Coverage Δ
unittests 100.00% <ø> (ø)
unittests-cp310-Linux 100.00% <ø> (ø)
unittests-cp310-Windows 100.00% <ø> (ø)
unittests-cp310-macOS 100.00% <ø> (ø)
unittests-cp311-Linux 100.00% <ø> (ø)
unittests-cp311-Windows 100.00% <ø> (ø)
unittests-cp311-macOS 100.00% <ø> (ø)
unittests-cp312-Linux 100.00% <ø> (ø)
unittests-cp312-Windows 100.00% <ø> (ø)
unittests-cp312-macOS 100.00% <ø> (ø)
unittests-cp313-Linux 100.00% <ø> (ø)
unittests-cp313-Windows 100.00% <ø> (ø)
unittests-cp313-macOS 100.00% <ø> (ø)
unittests-cp313t-Linux 100.00% <ø> (ø)
unittests-cp313t-Windows 100.00% <ø> (ø)
unittests-cp313t-macOS 100.00% <ø> (ø)
unittests-cp314-Linux 100.00% <ø> (ø)
unittests-cp314-Windows 100.00% <ø> (ø)
unittests-cp314-macOS 100.00% <ø> (ø)
unittests-cp314t-Linux 100.00% <ø> (ø)
unittests-cp314t-Windows 100.00% <ø> (ø)
unittests-cp314t-macOS 100.00% <ø> (ø)
unittests-cp315-Linux 100.00% <ø> (ø)
unittests-cp315-Windows 100.00% <ø> (ø)
unittests-cp315-macOS 100.00% <ø> (ø)
unittests-cp315t-Linux 100.00% <ø> (ø)
unittests-cp315t-Windows 100.00% <ø> (ø)
unittests-cp315t-macOS 100.00% <ø> (ø)
unittests-cp39-Linux 100.00% <ø> (ø)
unittests-cp39-Windows 100.00% <ø> (ø)
unittests-cp39-macOS 100.00% <ø> (ø)
unittests-pp311-Linux 100.00% <ø> (ø)
unittests-pp311-Windows 100.00% <ø> (ø)
unittests-pp311-macOS 100.00% <ø> (ø)
unittests-pydebug 100.00% <ø> (ø)
unittests-pydebug-cp310d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp310d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp310d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp311d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp311d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp311d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp312d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp312d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp312d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp313d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp313d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp313d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp313td-Linux 100.00% <ø> (ø)
unittests-pydebug-cp313td-Windows 100.00% <ø> (ø)
unittests-pydebug-cp313td-macOS 100.00% <ø> (ø)
unittests-pydebug-cp314d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp314d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp314d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp314td-Linux 100.00% <ø> (ø)
unittests-pydebug-cp314td-Windows 100.00% <ø> (ø)
unittests-pydebug-cp314td-macOS 100.00% <ø> (ø)
unittests-pydebug-cp315d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp315d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp315d-macOS 100.00% <ø> (ø)
unittests-pydebug-cp315td-Linux 100.00% <ø> (ø)
unittests-pydebug-cp315td-Windows 100.00% <ø> (ø)
unittests-pydebug-cp315td-macOS 100.00% <ø> (ø)
unittests-pydebug-cp39d-Linux 100.00% <ø> (ø)
unittests-pydebug-cp39d-Windows 100.00% <ø> (ø)
unittests-pydebug-cp39d-macOS 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@XuehaiPan
XuehaiPan merged commit 661edcc into metaopt:main Aug 21, 2026
201 of 393 checks passed
@XuehaiPan
XuehaiPan deleted the codex/fix-subinterpreter-finalization branch August 21, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cxx Something related to the CXX source code enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant