Debugging Extension Modules on Linux/Unix

Index of All Documentation » Wing Pro Reference Manual » Advanced Debugging Topics »

Gdb can be used as a tool to aid in debugging C/C++ extension modules written for Python, while also running code in Wing's Python debugger.

This section assumes you are already familiar with gdb; for more information on gdb commands, please refer to the gdb documentation.

Preparing Python

The first step in debugging C/C++ modules with gdb is to make sure that you are using a version of Python that was compiled with debug symbols. To do this, you need a source distribution of Python and you need to configure the distribution as described in the accompanying README file.

In most cases, this can be done as follows: (1) Type ./configure, (2) type make OPT=-g or edit the Makefile to add OPT=-g, and (3) type make. Once the build is complete you can optionally install it with make install (see the README first if you don't want to install into /usr/local/lib/python) but you can also run Python in place without installing it.

When this is complete, compile your extension module against that version of Python.

Starting Debug

In order to run code both within Wing's Python debugger and gdb, launch your debug process from Wing first, then note the process ID shown in the tooltip that appears when you hover the mouse over the debug icon in the lower left of Wing's main window.

Next, start gdb. First running emacs and then typing Esc-X gdb within emacs is one way of doing this, and this makes it easier to set breakpoints and view code as you go up and down the stack or step through it.

Within gdb, type attach <pid> where <pid> is replaced with the process ID reported by Wing. This will pause the process as it attaches, which gives you a chance to set breakpoints (in emacs you can do this with Ctrl-X Space while working in the editor). When you're ready to continue the process, type c in gdb.

You are now debugging both at the Python and C/C++ level. You should be able to pause, step, and view data in Wing whenever gdb is not paused. When gdb is paused, Wing's debugger cannot be used until the process is continued at the gdb level.

Tips and Tricks

(1) You may want to set up your ~/.gdbinit file by copying the contents of the file Misc/gdbinit from the Python source distribution. This contains some useful macros for inspecting Python code from gdb (for example pystack will print the Python stack, pylocals will print the Python locals, and pyframe prints the current Python stack frame)

(2) Note that breakpoints in a shared library cannot be set until after the shared library is loaded. If running your program triggers loading of your extension module library, you can use ^C^C to interrupt the debug program, set breakpoints, and then continue. Otherwise, you must continue running your program until the extension module is loaded. When in doubt, add a print statement at point of import, or you can set a breakpoint at PyImport_AddModule (this can be set after file python and before running since this call is not in a shared library).

(3) For viewing Python data from the C/C++ side when using gdb. The following gdb command will print out the contents of a PyObject * called obj as if you had issued the command print obj from within the Python language:

(gdb) p PyObject_Print (obj, stderr, 0)

For more information see Debugging with Gdb in the Python wiki.

(4) If you are launching code in a way that requires you to set LD_LIBRARY_PATH and this is not working, check whether this value is set in .cshrc. This file is read each time gdb runs so may overwrite your value. To work around this, set LD_LIBRARY_PATH in .profile instead. This file is read only once at login time.

(5) Some older versions of gdb will get confused if you load and unload shared libraries repeatedly during a single debug session. You can usually re-run Python 5-10 times but subsequently may see crashing, failure to stop at breakpoints, or other odd behaviors. When this occurs, there is no alternative but to exit and restart gdb.