Skip to content

Conversation

cxzhong
Copy link
Contributor

@cxzhong cxzhong commented Oct 9, 2025

I have refactor the atexit.pyx since for python 3.14, the changes of atexit is so much for supporting the nogil version.

Python<=3.13 Implementation:

  • The atexit module stores callbacks in a C array of structs (atexit_callback).
  • The structure is defined in C as:
typedef struct {  PyObject *func;    PyObject *args;    PyObject *kwargs;} atexit_callback;
  • Callbacks are stored in the interp->atexit.callbacks field as a C array
  • The array can be directly accessed from Cython code using pointer arithmetic

Python 3.14 Implementation:

  • The atexit module was refactored to use a Python PyList object instead of a C array.
  • The structure is now:
state.callbacks = [(func, args, kwargs), ...]  # A Python list of tuples
  • In the C implementation, callbacks are managed with:
PyObject *callbacks;  // This is now a PyList
  • Callbacks are inserted at the beginning (LIFO order) using PyList_Insert(state->callbacks, 0, callback)

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

⌛ Dependencies

Copy link

github-actions bot commented Oct 9, 2025

Documentation preview for this PR (built with commit 47bce83; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@tobiasdiez
Copy link
Contributor

tobiasdiez commented Oct 10, 2025

I would prefer to simply do nothing (or throw a 'is deprecated/removed' exception) in atexit for Python >= 3.13 (since it's not needed in this case as explained in #40890).

@cxzhong
Copy link
Contributor Author

cxzhong commented Oct 10, 2025

I would prefer to simply do nothing (or throw a 'is deprecated/removed' exception) in atexit for Python >= 3.13 (since it's not needed in this case as explained in #40890).

I just tested the doctest in atexit.pyx is OK but the order changed. The output is reversed.

@cxzhong
Copy link
Contributor Author

cxzhong commented Oct 10, 2025

I would prefer to simply do nothing (or throw a 'is deprecated/removed' exception) in atexit for Python >= 3.13 (since it's not needed in this case as explained in #40890).

I also think it is useless in Python 3.13+. We can edit the build system to exclude this. If Python version bigger than 3.13. But we need to modify forker.py, maybe we can do this when we drop support of python 3.12

Reversed the order of callbacks in atexit to maintain FIFO consistency with earlier versions, while noting changes in Python 3.14.
@cxzhong cxzhong changed the title TEST Refactor atexit.pyx Oct 11, 2025
@cxzhong cxzhong marked this pull request as ready for review October 12, 2025 04:57
@Copilot Copilot AI review requested due to automatic review settings October 12, 2025 04:57
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the atexit.pyx module to support both Python ≤3.13 and Python 3.14+, which changed how atexit callbacks are stored internally. The refactoring provides a uniform interface for accessing atexit callbacks across different Python versions.

  • Adds version-specific implementations for accessing atexit callbacks
  • Introduces C functions that handle both the legacy C array format (Python ≤3.13) and the new PyList format (Python 3.14+)
  • Updates the _get_exithandlers() function to work with both storage formats while maintaining consistent behavior

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +175 to +178
// Dummy function for Python 3.14+ (never called)
static atexit_callback_struct** get_atexit_callbacks_array(PyObject *self) {
return NULL;
}
Copy link

Copilot AI Oct 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning NULL from a dummy function could cause segmentation faults if accidentally called. Consider adding an assertion or error handling to make accidental calls more obvious during development.

Copilot uses AI. Check for mistakes.

Remove distutils macro definition for Py_BUILD_CORE.
@cxzhong cxzhong requested a review from dimpase October 13, 2025 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants