Credit: Joseph VanAndel, Michael Aivazis
A dynamically loaded C/C++ Python extension is giving you trouble on Unix or a Unix-like platform, and you would like to use the interactive debugger gdb to find out more about what’s wrong.
One way to find the cause of core dumps or other serious trouble with
a C Python extension is to compile the extension source with
-g
and then follow these steps (you may also want
to recompile any other extensions you use, such as Numeric, with
-g
):
% gdb /usr/bin/python2.1 (gdb) br _PyImport_LoadDynamicModule (gdb) cont # Repeat until your extension is loaded (gdb) finish # to load your extension (gdb) br wrap_myfunction # the entry point in your code (gdb) disable 1 # don't want to break for more modules being loaded (gdb) continue
If a dynamically loaded C/C++ extension is causing Python to core
dump, or causing some other kind of serious trouble, this recipe can
help you find out the root cause by showing a technique to debug your
extension using
gdb
(if you use Unix or a Unix-like platform, and
gdb is your debugger of choice). Note that the
overall concept generalizes to other debuggers with abilities similar
to gdb’s. You cannot set a
break on your function all at once, because your function lives in a
dynamic library (shared object) that isn’t initially
loaded. However, you can break in the
PyImport_LoadDynamicModule
function and eventually (when your module is at long last loaded) get
control at the debugger prompt after your module is in memory. You
will be able, at last, to set the breakpoint you need.
This technique works. However, if you often do this kind of thing, the process of stepping through all the modules, as Python loads them at startup, can easily become tedious. There’s a handier alternative, although it’s more invasive, because it requires you to modify your Python sources and rebuild Python from them.
The key idea of this handier alternative is to add a do-nothing
function somewhere in the body of code that Python loads immediately.
Specifically, you can edit the Modules/main.c
file to include one new function:
void Py_DebugTrap(void) { }
In whatever extension you’re debugging, add a call
to
Py_DebugTrap
right where you want to break into the code. The
Py_DebugTrap
symbol is immediately available when
you start gdb, because the symbol lives in
main.c
. So you can immediately set a breakpoint
there when you are at the gdb prompt, then
continue. This even works in parallel under MPI.
The gdb online documentation (just type
help
at the interactive prompt), manpages, and
online manual (http://www.gnu.org/manual/gdb-4.17/gdb.html).
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.