Repository navigation
compute error formatting state when python is initialized - #1936
Merged
Merged
Conversation
The hint is computed by R code, which can process events and re-enter conditionMessage_from_py_exception(); a re-entrant call deadlocked (libstdc++) or aborted (libc++) on the static's init guard. Fixes #1935.
Compute the error hint in R and look up traceback.format_exception_only() during initialization, instead of in function-local static initializers on the first error. Both initializers could run R code (the hint function, or the import hook's callback for 'traceback'), and a Python error formatted from there re-entered the static's init guard.
Cache the error hint when the namespace loads and read it from C++ during initialization. Keep the existing eight-argument R and native interfaces so callers that initialize Python directly continue to work.
Member
|
Thank you! |
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.
conditionMessage_from_py_exception()set up two function-local statics on the first Python error of a session, and both of their initializers could run R code:.py_last_error_hint();traceback.format_exception_only, whose first import oftracebackruns reticulate's import hook, which callspy_module_onload()in R.R code can process events. If an event handler formats another Python error in that window, the nested call waits on the static's own init guard: libstdc++ deadlocks and libc++ aborts. RStudio Server hit the deadlock while answering an Environment pane request as the Python REPL started; see #1935 for the backtrace.
Both are now set when Python is initialized. R computes the hint before Python starts and passes it to
py_initialize().py_initialize()looks uptraceback.format_exception_onlybefore anything that can raise a Python error, and before reticulate's import hook is installed. Formatting an error no longer computes either one.Testing
Two new tests in
test-python-exceptions.R, each run in a freshcallrsession:.py_last_error_hint()with a function that errors, after Python has started, then formats a Python error. On reticulate 1.47.0 the message is the replacement's error; with this branch it's the Python error plus the hint.py_register_load_hook("traceback", ...)hook that formats another Python error, then raises a first error. On macOS with 1.47.0 the child aborts with__cxa_guard_acquire detected recursive initialization; with this branch it passes.The rest of
test-python-exceptions.Rpasses. In the full suite the only failures were snapshot tests intest-py_require.R, which fail locally because of my uv version and default Python (3.13 vs 3.12).Fixes #1935.