Skip to content

Backport: Fix crash in getcurrent()/greenlet during early Py_FinalizeEx (3.2.6)#500

Open
nbouvrette wants to merge 2 commits intopython-greenlet:maint/3.2from
nbouvrette:fix/safe-getcurrent-during-finalization-3.2
Open

Backport: Fix crash in getcurrent()/greenlet during early Py_FinalizeEx (3.2.6)#500
nbouvrette wants to merge 2 commits intopython-greenlet:maint/3.2from
nbouvrette:fix/safe-getcurrent-during-finalization-3.2

Conversation

@nbouvrette
Copy link
Contributor

Summary

Backports all crash fixes from PR #499 (targeting main for 3.3.3) to the maint/3.2 branch for a 3.2.6 release, providing stability fixes for Python 3.9 users.

While regression-testing greenlet 3.2.5 (the backport of PR #495) against Python 3.9.7 under uWSGI, we discovered three additional crash paths during Py_FinalizeEx that were not fixed by PR #495:

  1. clear_deleteme_list() allocator crash: The vector copy used PythonAllocator (PyMem_Malloc), which can SIGSEGV during early Py_FinalizeEx when Python's allocator pools are partially torn down. Replaced with std::swap (zero-allocation) and switched deleteme_t to std::allocator.

  2. ThreadState memory corruption: ThreadState objects were allocated via PyObject_Malloc, placing them in pymalloc pools that can be disrupted during finalization. Switched to std::malloc/std::free.

  3. getcurrent() crash on invalidated type objects: _Py_IsFinalizing() is only set after call_py_exitfuncs completes inside Py_FinalizeEx, so atexit handlers could still call greenlet.getcurrent() when type objects had been invalidated. An atexit handler now sets a shutdown flag before any other cleanup runs.

  4. Exception preservation: clear_deleteme_list() now preserves pending exceptions around its cleanup loop.

All new code is guarded by #if !GREENLET_PY311 — zero impact on Python 3.11+.

Additional changes

  • Py_IsFinalizing() compat shim: Maps the public API name (available since Python 3.13) to _Py_IsFinalizing() on older versions. All call sites now use the standard name; remove the two-line shim when < 3.13 is dropped.
  • Windows USS tolerance: Adds a 512 KB tolerance to the USS memory test on Windows to prevent flaky CI failures from OS-level measurement noise.
  • Additional shutdown tests: Ports the new test_interpreter_shutdown.py tests covering atexit-registered greenlet construction and cross-thread cleanup.

Test plan

  • Existing test suite passes
  • New test_interpreter_shutdown.py tests pass
  • Manual uWSGI stress test: 0 segfaults in 600 requests with worker recycling on Python 3.9.7 (greenlet reports 3.2.6.dev0)
  • CI on all supported Python versions (3.9–3.14)

Relationship to PR #499

This is a manual port (not cherry-pick) of PR #499's crash fixes, adapted to the maint/3.2 code structure which differs from main in several ways (no free-threading support, setup.py vs pyproject.toml, different allocator layout, etc.). The crash fix logic is identical.

Made with Cursor

Ports all crash fixes from the main branch (PR python-greenlet#499) to maint/3.2 for
a 3.2.6 release targeting Python 3.9 stability.

Three root causes of SIGSEGV during Py_FinalizeEx on Python < 3.11:

1. clear_deleteme_list() vector allocation crash: replaced copy with
   std::swap and switched deleteme_t to std::allocator (system malloc).

2. ThreadState memory corruption: switched from PythonAllocator
   (PyObject_Malloc) to std::malloc/std::free.

3. getcurrent() crash on invalidated type objects: added atexit handler
   that sets g_greenlet_shutting_down before _Py_IsFinalizing() is set.

Also fixes exception preservation in clear_deleteme_list(), adds
Py_IsFinalizing() compat shim for Python < 3.13, Windows USS tolerance
for flaky memory test, and additional shutdown tests.

Made-with: Cursor
The SPDX identifier "Python-2.0" refers to the Python 2.0 license,
which is not GPL-compatible.  The correct identifier for the PSF
license used by greenlet is "PSF-2.0", which is GPL-compatible.

Backport of 77e65f0 from master.

Made-with: Cursor
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.

1 participant