Closed tuliom closed 8 months ago
@llvm/issue-subscribers-lldb
Author: Tulio Magno Quites Machado Filho (tuliom)
@tuliom How far did you get here? I know you were able to do some work with LLDB's Python usage, is the failure list still at those 19?
I assume we (the LLDB maintainers) will need to contend with this at some point in the near future, so thank you for opening this issue.
FWIW I also just hit this with Python 3.12.
@tuliom How far did you get here? I know you were able to do some work with LLDB's Python usage, is the failure list still at those 19?
@bulbazord I didn't start working on this issue. The 19 failures are remaining failures after my recent changes. I'm afraid that a larger re-design of the plugins mechanism is required in order to solve this issue.
@tuliom How far did you get here? I know you were able to do some work with LLDB's Python usage, is the failure list still at those 19?
@bulbazord I didn't start working on this issue. The 19 failures are remaining failures after my recent changes. I'm afraid that a larger re-design of the plugins mechanism is required in order to solve this issue.
Gotcha. Redesigning the python plugins is no small task but it will have to be done eventually. Thanks for bringing this to our attention.
On Fedora 39, with the python3-lldb
package installed (Python 3.12.0, LLVM 17.0.4), all one has to do to get this crash is:
$ python3
>>> import lldb
This leaves the Scripting Bridge API essentially unusable.
Of course, OP might be familiar with this, being the packager of said Fedora package... :)
EDIT: One workaround is to install the python3.11
package, and start the interpreter like this: PYTHONPATH=$(lldb -P) python3.11
[source].
@tuliom
While trying to update lldb to work with Python >= 3.12, I found the following issue: Starting with Python 3.12, there is code now preventing the usage of
PyImport_AppendInittab
afterPy_Initialize()
.
Which sounds like a whole big mess, except for this one tantalizing note in the Python C API docs on initialization
If Python is initialized multiple times,
PyImport_AppendInittab()
orPyImport_ExtendInittab()
must be called before each Python initialization.
While lldb can't control what other code has done before running python, including possibly initializing it, perhaps it's possible to reinitialize it, and therefore have access to PyImport_AppendInittab()
again.
Presumably that would only be possible when embedding Python into LLDB using the C API, where the initialization can be adjusted ahead-of-time. Whereas the extension module might be better off avoiding any attempts to meddle with the Python initialization.
After all, what if the environment is an already-initialized, standalone Python interpreter that's only now loading the extension? Like in @torokati44's example of typing import lldb
at the REPL prompt. Not only is Python readline already loaded, there, but it's active and managing interactive state for the user. Swapping it out in that context sounds like a Bad Time™.
cc: @bulbazord
This came up again today and I decided to give this another go. I've convinced myself that it's safe (and correct) to guard the call to PyImport_AppendInittab
behind a check that Python hasn't been initialized yet. I've explained my reasoning in #82095.
The two remaining unit test failures are a different issue with Python 3.12 that I haven't figured out yet. The reason I think that is because the tests don't actually use anything from the lldb module, and the issue also reproduces when skipping the call to ScriptInterpreterPythonImpl::Initialize
and doing it by hand (#82096).
Until this is released, and gets included in the majority of the mainstream distros...
I had the brilliant idea of somehow using lldb
and its script
command as if it was a python3
interpreter, with its own binding module already loaded.
Can this work? Is this silly?
Of course, one could write a small C++ program that uses CommandObjectScript::DoExecute
, or ScriptInterpreterPython
, or just InitializePythonRAII
, to get the same thing.
The problem with this is that I don't know whether this can be achieved through the SB API alone - and if not, that will be dependent on the installed LLVM version, which we'd like to avoid...
It's possible I've just got lost in a maze of twisty commits, but it looks like this fix didn't make it into LLDB 18 and also missed the cut for the LLDB 19 branch (or at least, it wasn't at the point tagged llvmorg-19-init). Please could it be merged across before LLDB 19 goes live? I've got some testing of visualisers that uses the scripting bridge to manage the tests, and I'd rather not be stuck running the tests on 17 any longer than necessary.
Of course, if there's a workaround, that'd be great. But the only suggestion I've seen above doesn't work (ImportError: cannot import name '_lldb' from partially initialized module 'lldb' (most likely due to a circular import)
This also breaks python's own help function:
python3 -c "help('modules')"
Results in
Fatal Python error: PyImport_AppendInittab: PyImport_AppendInittab() may not be called after Py_Initialize()
Python runtime state: initialized
Current thread 0x00007cbe700e3740 (most recent call first):
File "/usr/lib/python3.12/site-packages/lldb/__init__.py", line 4327 in Initialize
File "/usr/lib/python3.12/site-packages/lldb/__init__.py", line 15710 in <module>
File "<frozen importlib._bootstrap>", line 488 in _call_with_frames_removed
File "<frozen importlib._bootstrap_external>", line 995 in exec_module
File "<frozen importlib._bootstrap>", line 935 in _load_unlocked
File "<frozen importlib._bootstrap>", line 1331 in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1360 in _find_and_load
File "/usr/lib/python3.12/pkgutil.py", line 78 in walk_packages
File "/usr/lib/python3.12/pydoc.py", line 2328 in run
File "/usr/lib/python3.12/pydoc.py", line 2299 in listmodules
File "/usr/lib/python3.12/pydoc.py", line 2145 in help
File "/usr/lib/python3.12/pydoc.py", line 2096 in __call__
File "<frozen _sitebuiltins>", line 103 in __call__
File "<string>", line 1 in <module>
Extension modules: pyalpm, yaml._yaml, google.protobuf.pyext._message, google3.net.proto2.python.internal.cpp._message, PyQt6.QtCore, PyQt6.QtGui, PyQt6.QtNetwork, PyQt6.QtQml, PyQt6.QtQuick, PyQt6.QtWebChannel, PyQt6.QtWebEngineCore, PyQt6.QtWidgets, PyQt6.QtPrintSupport, PyQt6.QtWebEngineWidgets, gi._gi, cairo._cairo, gi._gi_cairo, markupsafe._speedups, lxml._elementpath, lxml.etree, _dbus_bindings, _blueman, breezy._chunks_to_lines_pyx, breezy._known_graph_pyx, breezy.bzr._simple_set_pyx, breezy.bzr._static_tuple_c, msgpack._cmsgpack, _cffi_backend, evdev._input, evdev._ecodes, evdev._uinput, fastbencode._bencode_pyx, PyQt5.QtCore, PyQt5.QtGui, PyQt5.QtWidgets, PyQt5.QtNetwork, PyQt5.QtSvg, gpg._gpgme, mercurial.cext.parsers, mercurial.zstd, mercurial.thirdparty.sha1dc, mercurial.cext.osutil, mercurial.cext.base85, mercurial.cext.bdiff, mercurial.cext.mpatch, libsvn._client, libsvn._core, libsvn._delta, libsvn._wc, libsvn._ra, hgext.fsmonitor.pywatchman.bser, multidict._multidict, libmount.pylibmount, lldb._lldb (total: 54)
zsh: IOT instruction (core dumped) python3 -c "help('modules')"
@jendrikw
That pydoc
has to import a module to extract its documentation is a known issue with it, and there are a lot of modules that break it. Try running a python3 -m pydoc -k <term>
search some time (doesn't matter what the term is), and watch how much noise is spewed while it walks the various packages. Ifyou're lucky lldb
is the only one that actually crashes it, I've seen plenty others.
But as far as the current LLDB Python extension goes, until this fix is released it doesn't work anyway, so it's pretty useless to have installed. The simplest solution is probably to just remove /usr/lib/python3.12/site-packages/lldb
entirely. (Whether that involves using pip
, or your distro package manager, or what have you...)
On Fedora it's sudo dnf remove python3-lldb
. That'll also force removal of lldb-devel
, which may or may not be a problem. YMMV, of course.
@JDevlieghere Thanks for your submission. I still encounter this problem on lldb 18. It seems that the fix has not been merged into the mainline. Will it be merged in the upcoming version?
cc: @bulbazord
While trying to update lldb to work with Python >= 3.12, I found the following issue:
Starting with Python 3.12, there is code now preventing the usage of
PyImport_AppendInittab
afterPy_Initialize()
. However, according to this source code comment:This is causing the following failures:
With the following output:
One can reduce the list of failures to 2 by guaranteeing the critical code in
InitializePythonRAII()
is executed only once. But it still doesn't solve all the cases.