Bug 639392

Summary: Generating python backtrace with "py-bt" fails with a traceback
Product: Red Hat Enterprise Linux 6 Reporter: Petr Šplíchal <psplicha>
Component: pythonAssignee: Dave Malcolm <dmalcolm>
Status: CLOSED ERRATA QA Contact: Petr Šplíchal <psplicha>
Severity: medium Docs Contact:
Priority: low    
Version: 6.0CC: ohudlick
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: python-2.6.6-9.el6 Doc Type: Bug Fix
Doc Text:
On AMD64 and Intel 64 architectures, running gdb (configured using "--with-python") on python applications to generate backtraces caused a traceback error. python-gdb.py, the python module that deals with the case of debugging a python process, was updated to prevent this.
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-05-19 11:37:05 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Petr Šplíchal 2010-10-01 16:02:50 UTC
Description of problem:

Using python gdb command "py-bt" to generate backtrace results in
a python traceback. This is x86_64-only, works fine on all other
architectures.

# rpm -q python gdb

    python-2.6.5-3.el6.x86_64
    gdb-7.1-29.el6.x86_64

# cat foo.py
    class Foo:
        def bar(self):
            from ctypes import string_at
            string_at(0xDEADBEEF) # this code will cause Python to segfault

    f = Foo()

    # Let's assign some data of various kinds to the instance:
    f.someattr = 42
    f.someotherattr = {'one':1, 'two':2L, 'three':[(), (None,), (None, None)]}

    # Now let's trigger the segfault
    f.bar()

# gdb -q --args python foo.py

Reading symbols from /usr/bin/python...Reading symbols from
/usr/lib/debug/usr/bin/python2.6.debug...done.
done.
(gdb) r
Starting program: /usr/bin/python foo.py
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/strlen.S:31
31  pcmpeqb (%rdi), %xmm2

(gdb) py-bt
#10 (unable to read python frame information)
#14 (unable to read python frame information)
Traceback (most recent call last):
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 1326,
in invoke
    frame.print_summary()
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 1181,
in print_summary
    pyop = self.get_pyop()
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 1154,
in get_pyop
    return PyFrameObjectPtr.from_pyobject_ptr(f)
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 349,
in from_pyobject_ptr
    return cls(gdbval)
TypeError: __init__() takes exactly 3 arguments (2 given)
Error occurred in Python command.

Comment 1 Dave Malcolm 2010-10-01 17:40:48 UTC
The code in question is the error-handling pass here (still present in upstream code):
        try:
            p = PyObjectPtr(gdbval)
            cls = cls.subclass_from_type(p.type())
            return cls(gdbval, cast_to=cls.get_gdb_type())
        except RuntimeError:
            # Handle any kind of error e.g. NULL ptrs by simply using the base
            # class
            pass
        return cls(gdbval)

I've seen this backtrace from time to time; haven't yet been able to reproduce it at will.  It should be possible to fix this by replacing the above with something like:
        p = PyObjectPtr(gdbval)
        try:
            cls = cls.subclass_from_type(p.type())
            return cls(gdbval, cast_to=cls.get_gdb_type())
        except RuntimeError:
            # Handle any kind of error e.g. NULL ptrs by simply using the base
            # class
            pass
        return p

though I'm not yet sure if that's the correct fix.

Comment 2 Dave Malcolm 2011-01-19 22:19:57 UTC
Correction:
  the reproducer in comment #0 does reliably reproduce this for me (on x86_64)

Trying the approach in comment #1 doesn't work; I get:
Traceback (most recent call last):
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 1325, in invoke
    frame.print_summary()
  File "/usr/lib/debug/usr/lib64/libpython2.6.so.1.0.debug-gdb.py", line 1183, in print_summary
    sys.stdout.write(pyop.current_line())
AttributeError: 'PyObjectPtr' object has no attribute 'current_line'
Error occurred in Python command: 'PyObjectPtr' object has no attribute 'current_line'

Comment 6 Laura Bailey 2011-05-10 01:00:56 UTC
    Technical note added. If any revisions are required, please edit the "Technical Notes" field
    accordingly. All revisions will be proofread by the Engineering Content Services team.
    
    New Contents:
On AMD64 and Intel 64 architectures, running gdb (configured using "--with-python") on python applications to generate backtraces caused a traceback error. python-gdb.py, the python module that deals with the case of debugging a python process, was updated to prevent this.

Comment 7 errata-xmlrpc 2011-05-19 11:37:05 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2011-0554.html

Comment 8 errata-xmlrpc 2011-05-19 13:07:43 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2011-0554.html