Python tracks segmentation error

I am developing C extensions from python ad. I get some segfaults (unavoidable during development ...).

I'm looking for a way to display on which line of code segfault happens (the idea is like tracking every line of code), how can I do this?

+38
c python debugging
Apr 18 '10 at 20:35
source share
4 answers

Here you can display the file name and line number of each line of Python in which your code runs:

import sys def trace(frame, event, arg): print "%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno) return trace def test(): print "Line 8" print "Line 9" sys.settrace(trace) test() 

Output:

 call, test.py:7 line, test.py:8 Line 8 line, test.py:9 Line 9 return, test.py:9 

(Of course, you probably want to write the trace output to a file.)

+31
Apr 18 '10 at 20:41
source share

If you are using linux, run python under gdb

 gdb python (gdb) run /path/to/script.py ## wait for segfault ## (gdb) backtrace ## stack trace of the c code 
+52
Apr 18 '10 at 22:23
source share

Segfaults from C extensions are very often the result of not increasing the number of links when creating a new object reference. This makes them very difficult to track, since segfault only occurs after the last link is removed from the object, and even then often only when some other object is highlighted.

You do not say how much C extension code you have written, but if you are just starting out, consider whether you can use ctypes or Cython . Ctypes may not be flexible enough for your needs, but you should be able to reference any C library with Cython and automatically maintain all link counts.

This is not always enough: if your Python objects and any underlying C objects have different lifetimes, you can still get problems, but it will greatly simplify the situation.

+15
Apr 19 '10 at 12:48
source share

There are several undocumented python extensions for gdb.

From the source of the Python Tools/gdb/libpython.py (it is not part of the normal installation).

Put it in sys.path

Then:

 # gdb /gps/python2.7_x64/bin/python coredump ... Core was generated by `/usr/bin/python script.py'. Program terminated with signal 11, Segmentation fault. #0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037 ... (gdb) python >import libpython > >end (gdb) bt #0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037 #1 PyEval_EvalFrameEx (f=f@entry= Frame 0x7f9084d20ad0, for file /usr/lib/python2.7/site-packages/librabbitmq/__init__.py, line 220, in drain_events (self=<Connection(channels={1: <Channel(channel_id=1, connection=<...>, is_open=True, connect_timeout=4, _default_channel=<....(truncated), throwflag=throwflag@entry=0) at Python/ceval.c:2681 ... (gdb) py-list 218 else: 219 timeout = float(timeout) >220 self._basic_recv(timeout) 221 222 def channel(self, channel_id=None): 

As you can see, now we see the visibility on the Python stack corresponding to the CPython call chain.

Some reservations:

  • Your gdb version must be greater than 7 and must be compiled with --with-python
  • gdb injects python (by referencing libpython ), it does not run it in a subshell. This means that it may not match the python version that is on $PATH .
  • You need to download libpython.py from any version of the Python source that matches any gdb .
  • You may need to run gdb as root - if you may need to configure sys.path to match what you are debugging.

If you cannot copy libpython.py to sys.path , you can add it to sys.path as follows:

 (gdb) python >import sys >sys.path.append('/path/to/containing/dir/') >import libpython > >end 

This is a bit poorly documented in python dev docs , federal wiki and python wiki

If you have an older gdb or just can't work it, the Python source also has gdbinit , you can copy to ~/.gdbinit , which add some similar functions

+3
Jun 24 '15 at 15:11
source share



All Articles