This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [python] Crash when using generators with Python 2.4


For completeness, the assertion in genobject.c is correct starting
from Python 2.5.0
(http://svn.python.org/view/python/tags/r25/Objects/genobject.c?rev=51918&view=markup),
although I haven't checked that gdb can run generators compiled
against 2.5.

I checked with Brett Cannon (who's been hacking on Python internals
longer than I have), and he couldn't think of a third option either.
If you guys decide to manufacture a frame object, there's an example
of doing so at http://svn.python.org/view/python/tags/r246/Modules/pyexpat.c?rev=67853&view=markup.
They create a dummy code object in getcode() and create the dummy
frame with PyFrame_New() in call_with_frame().

Jeffrey

On Fri, Jan 16, 2009 at 10:47 AM, Paul Pluzhnikov
<ppluzhnikov@google.com> wrote:
> Greetings,
>
> One of my end-users wrote a pretty printer using Python generator,
> and discovered that doing this crashes gdb+python.
>
> Here is a test case: replace Tom's StdListPrinter with this one:
>
> class StdListPrinter:
>    "Print a std::list"
>
>    def __init__(self, val):
>        self.val = val
>
>    def children(self):
>        itype = self.val.type().template_argument(0)
>        nodetype = gdb.Type('std::_List_node<%s>' % itype).pointer()
>        head = self.val['_M_impl']['_M_node']
>        base = head['_M_next']
>        head = head.address()
>        count = 0
>        while base != head:
>            elt = base.cast(self.nodetype).dereference()
>            base = elt['_M_next']
>            yield ('[%d]' % count, elt['_M_data'])
>            count += 1
>
>    def to_string(self):
>        if self.val['_M_impl']['_M_node'].address() == self.val['_M_impl']['_M_node']['_M_next']:
>            return 'empty std::list'
>        return 'std::list'
>
>
> Configure gdb+python to use Python 2.4, print an instance of
> std::list, and you'll see:
>
> gdb: Objects/genobject.c:53: gen_iternext: Assertion `f->f_back != ((void *)0)' failed.
> $1 = std::list
> Program received signal SIGABRT, Aborted.
>
> (top) bt
> #0  0x00002aaaabbf1c75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
> #1  0x00002aaaabbf3620 in *__GI_abort () at ../sysdeps/generic/abort.c:88
> #2  0x00002aaaabbeb6d4 in *__GI___assert_fail (assertion=0x8deea9 "f->f_back != ((void *)0)", file=0x8dee3d "Objects/genobject.c", line=53, function=0x8dee67 "gen_iternext") at assert.c:83
> #3  0x000000000077f3af in gen_iternext (gen=0x1608f90) at Objects/genobject.c:53
> #4  0x00000000006ce090 in PyIter_Next (iter=0x1608f90) at Objects/abstract.c:2253
> #5  0x000000000046a1d8 in print_children (printer=0x15cf360, hint=0x0, stream=0xb3bd80, recurse=0, options=0x7fffffffdd10, language=0x7f2260) at ../../gdb/python/python.c:1081
> #6  0x000000000046a5e1 in apply_val_pretty_printer (type=0xe62bc8, valaddr=0xd98010 "À\220A", embedded_offset=0, address=140737488348304, stream=0xb3bd80, recurse=0, options=0x7fffffffdd10, language=0x7f2260) at ../../gdb/python/python.c:1238
> #7  0x00000000004a9843 in value_print (val=0x136dbf0, stream=0xb3bd80, options=0x7fffffffdd10) at ../../gdb/valprint.c:353
> #8  0x00000000004abed1 in print_formatted (val=0x136dbf0, size=0, options=0x7fffffffdd10, stream=0xb3bd80) at ../../gdb/printcmd.c:305
> #9  0x00000000004ad078 in print_command_1 (exp=0xa120f2 "ls", inspect=0, voidprint=1) at ../../gdb/printcmd.c:914
> ...
>
>  "ls" in frame #9 is an instance of 'std::list<std::string>'
>  frames #3 and #4 are in Python
>
>
> The actual crash happens inside Python, because it expects to have
> a python frame above any routine which calls yield, and asserts so.
>
> Python 2.6 removes that expectation/assertion, and the above pretty
> printer produces expected:
>
> (gdb) p ls
> $1 = std::list
>
> I see two ways to fix this:
>
> A. somehow push a "dummy" Python frame before calling next() on
>   the iterator returned from children() [I don't know how exactly to
>   do that], or
> B. disallow generators as return from children() if GDB was built
>   with Python 2.4 [I believe I know how to do that.]
>
> A) has the advantage that the same pretty printers will work
> regardless of which Python was used; but it is more of a hack.
>
> Comments?
>
> --
> Paul Pluzhnikov
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]