Add safe GIL helpers for Python 3.12+ and 3.13t compatibility#3
Merged
Add safe GIL helpers for Python 3.12+ and 3.13t compatibility#3
Conversation
297059d to
84f3570
Compare
- Add gil_acquire()/gil_release() helpers that check PyGILState_Check() before calling PyGILState_Ensure() to avoid double-acquisition - Add per-interpreter event loop storage infrastructure (not yet used) for future sub-interpreter support The per-interpreter storage functions are defined but not called yet. This commit only adds infrastructure without changing behavior.
84f3570 to
d557289
Compare
- Replace global g_python_event_loop usage with per-interpreter lookup via get_interpreter_event_loop() in all Python-callable functions - Set per-interpreter storage in nif_set_python_event_loop and create_default_event_loop to ensure proper loop binding - Clear per-interpreter storage in event_loop_destructor when loop is destroyed to prevent stale references - Use per-call ErlNifEnv for timer scheduling/cancellation to prevent races in free-threaded Python mode - Fail fast on RuntimeError in erlang_loop.py instead of silently swallowing initialization errors that cause hangs This fixes py_async_e2e_SUITE timeouts caused by stale event loop references after test restarts and enables proper sub-interpreter event loop isolation.
The per-interpreter event loop lookup now falls back to the global g_python_event_loop when the per-interpreter storage is not set. This ensures compatibility when the module attribute hasn't been initialized yet or in environments where the per-interpreter storage setup fails silently.
- Simplify get_interpreter_event_loop() to use global pointer directly, avoiding per-interpreter module attribute lookup issues on Python 3.12+ - Force async worker threads in py_callback.c to use SelectorEventLoop directly, bypassing the policy to avoid ErlangEventLoop conflicts - Update ErlangEventLoopPolicy to only return ErlangEventLoop for the main thread; worker threads get default SelectorEventLoop The ErlangEventLoop is designed for the main execution thread where the Erlang event router is available. Worker threads need independent event loops that don't depend on the Erlang-native infrastructure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
gil_acquire()/gil_release()helpers that checkPyGILState_Check()before callingPyGILState_Ensure()to avoid double-acquisition issues on Python 3.12+Based on analysis of PyO3 and Python docs,
PyGILState_Ensure()/PyGILState_Release()work correctly in both GIL-enabled and free-threaded builds.