Bug 12555

Summary: Hangup in MI commands if python StdStringPrinter used on uninitialized std::string
Product: gdb Reporter: Jens Elmenthaler <jens.elmenthaler>
Component: miAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: aegges, andre.poenitz, asmwarrior, dodji, marc.khouzam, pmuldoon, tromey, vladimir, xgsa
Priority: P2    
Version: 7.1   
Target Milestone: 7.4   
Host: Target:
Build: Last reconfirmed:

Description Jens Elmenthaler 2011-03-09 16:03:16 UTC
I have the following code, in combination with the STL pretty printers:

int main() {
    vector<string> names; // Break point here
    names.push_back("German");
    names.push_back("Hola");
    names.push_back("Adios");

    names.pop_back();
    return 0;
}

When the debugger stops at the line declaring "names", gdb hangs, keeping my linux machine very busy. The problem is that gdb is busy in a MI command sent by my graphical frontend retrieving all the characters of an uninitialized string, as the following stack trace shows:

#0  0x0000003d410c38a3 in __pread_nocancel () from /lib64/libc.so.6
#1  0x0000000000492d39 in linux_proc_xfer_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    readbuf=0x2af934ef9bb8 "", writebuf=0x0, offset=263084223400, len=8459111) at linux-nat.c:4774
#2  0x0000000000493d0e in linux_xfer_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    readbuf=0x2af934ef9bb8 "", writebuf=0x0, offset=263084223400, len=8459111) at linux-nat.c:5103
#3  0x0000000000490a36 in linux_nat_xfer_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    readbuf=0x2af934ef9bb8 "", writebuf=0x0, offset=263084223400, len=8459111) at linux-nat.c:3972
#4  0x0000000000586761 in memory_xfer_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, readbuf=0x2af934ef9bb8,
    writebuf=0x0, memaddr=263084223400, len=8459111) at target.c:1335
#5  0x00000000005868e4 in target_xfer_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    readbuf=0x2af934ef9bb8, writebuf=0x0, offset=263084223400, len=8459111) at target.c:1403
#6  0x0000000000587216 in target_read_partial (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    buf=0x2af934ef9bb8 "", offset=263084223400, len=8459111) at target.c:1679
#7  0x00000000005872dd in target_read (ops=0x17b95ed0, object=TARGET_OBJECT_MEMORY, annex=0x0,
    buf=0x2af934ec9010 "H\203\372\001H\211\370u\004@\210\067\303I\271\001\001\001\001\001\001\001\001I\211\320H\017\266\326I\017\257\321I\201\370\220", offset=263084023808, len=8658703) at target.c:1706
#8  0x0000000000586b31 in target_read_memory (memaddr=263084023808,
    myaddr=0x2af934ec9010 "H\203\372\001H\211\370u\004@\210\067\303I\271\001\001\001\001\001\001\001\001I\211\320H\017\266\326I\017\257\321I\201\370\220", len=8658703) at target.c:1479
#9  0x000000000052a029 in partial_memory_read (memaddr=263084023808,
    myaddr=0x2af934ec9010 "H\203\372\001H\211\370u\004@\210\067\303I\271\001\001\001\001\001\001\001\001I\211\320H\017\266\326I\017\257\321I\201\370\220", len=8658703, errnoptr=0x7fff762b8818) at valprint.c:1223
#10 0x000000000052a14f in read_string (addr=263084023808, len=8658703, width=1, fetchlimit=8658703,
    byte_order=BFD_ENDIAN_LITTLE, buffer=0x7fff762b88c8, bytes_read=0x7fff762b88d4) at valprint.c:1307
#11 0x00000000004df146 in gdbpy_extract_lazy_string (string=0x2af9348baed0, str_type=0x7fff762b89e8,
    length=0x7fff762b89f0, encoding=0x7fff762b89e0) at ./python/py-lazy-string.c:207
#12 0x00000000004dfd29 in print_string_repr (printer=0x2af93487bb48, hint=0x17ec55c0 "string", stream=0x17ed5a60,
    recurse=1, options=0x7fff762b8f30, language=0x7c9e60, gdbarch=0x17c9a8f0) at ./python/py-prettyprint.c:205
#13 0x00000000004e0915 in apply_val_pretty_printer (type=0x17d69d10, valaddr=0x17fea880 "", embedded_offset=0,
    address=263083557952, stream=0x17ed5a60, recurse=1, options=0x7fff762b8f30, language=0x7c9e60)
    at ./python/py-prettyprint.c:560
#14 0x000000000052885f in val_print (type=0x17d69d10, valaddr=0x17fea880 "", embedded_offset=0,
    address=263083557952, stream=0x17ed5a60, recurse=1, options=0x7fff762b8f30, language=0x7c9e60) at valprint.c:292
#15 0x0000000000528adb in common_val_print (val=0x17f5e510, stream=0x17ed5a60, recurse=1, options=0x7fff762b8f30,
    language=0x7c9e60) at valprint.c:364
#16 0x00000000004e0702 in print_children (printer=0x2af9349cd878, hint=0x17e7ef90 "array", stream=0x17ed5a60,
    recurse=0, options=0x7fff762b8f30, language=0x7c9e60) at ./python/py-prettyprint.c:489
#17 0x00000000004e0934 in apply_val_pretty_printer (type=0x17d8b240, valaddr=0x17ecaf90 "P\201", embedded_offset=0,
    address=140737488339984, stream=0x17ed5a60, recurse=0, options=0x7fff762b8f30, language=0x7c9e60)
    at ./python/py-prettyprint.c:562
#18 0x000000000052885f in val_print (type=0x17d8b240, valaddr=0x17ecaf90 "P\201", embedded_offset=0,
    address=140737488339984, stream=0x17ed5a60, recurse=0, options=0x7fff762b8f30, language=0x7c9e60)
    at valprint.c:292
#19 0x0000000000528adb in common_val_print (val=0x17ecad00, stream=0x17ed5a60, recurse=0, options=0x7fff762b8f30,
    language=0x7c9e60) at valprint.c:364
#20 0x00000000004ca677 in list_args_or_locals (what=locals, values=1, fi=0x17bd9ad0) at ./mi/mi-cmd-stack.c:354
#21 0x00000000004ca0b1 in mi_cmd_stack_list_locals (command=0x17e72ae0 "stack-list-locals", argv=0x17c55bb0, argc=1)
    at ./mi/mi-cmd-stack.c:155
#22 0x00000000004cf5b8 in mi_cmd_execute (parse=0x17c55a40) at ./mi/mi-main.c:1715
#23 0x00000000004cee89 in captured_mi_execute_command (uiout=0x17be51b0, data=0x17c55a40) at ./mi/mi-main.c:1517
#24 0x000000000056124e in catch_exception (uiout=0x17be51b0, func=0x4cedbb <captured_mi_execute_command>,
    func_args=0x17c55a40, mask=6) at exceptions.c:462
#25 0x00000000004cf10f in mi_execute_command (cmd=0x17faa3d0 "26-stack-list-locals --thread 1 --frame 0 1",
    from_tty=1) at ./mi/mi-main.c:1613
#26 0x00000000004cb550 in mi_execute_command_wrapper (cmd=0x17faa3d0 "26-stack-list-locals --thread 1 --frame 0 1")
    at ./mi/mi-interp.c:251
#27 0x000000000056982e in gdb_readline2 (client_data=0x0) at event-top.c:817
#28 0x0000000000568e14 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:433
#29 0x000000000056758f in handle_file_event (data=...) at event-loop.c:811
#30 0x0000000000566bf9 in process_event () at event-loop.c:393
#31 0x0000000000566cd9 in gdb_do_one_event (data=0x0) at event-loop.c:458
#32 0x00000000005613fc in catch_errors (func=0x566c0e <gdb_do_one_event>, func_args=0x0, errstring=0x7a3ff8 "",
    mask=6) at exceptions.c:510
#33 0x0000000000566d15 in start_event_loop () at event-loop.c:482
#34 0x00000000004cb5b9 in mi_command_loop (mi_version=2) at ./mi/mi-interp.c:281
#35 0x00000000004cb570 in mi2_command_loop () at ./mi/mi-interp.c:263
#36 0x00000000005619c6 in current_interp_command_loop () at interps.c:288
#37 0x000000000044c563 in captured_command_loop (data=0x0) at ./main.c:226
#38 0x00000000005613fc in catch_errors (func=0x44c552 <captured_command_loop>, func_args=0x0, errstring=0x75a3e7 "",
    mask=6) at exceptions.c:510
#39 0x000000000044d5bf in captured_main (data=0x7fff762b9680) at ./main.c:905
#40 0x00000000005613fc in catch_errors (func=0x44c595 <captured_main>, func_args=0x7fff762b9680,
    errstring=0x75a3e7 "", mask=6) at exceptions.c:510
#41 0x000000000044d5f2 in gdb_main (args=0x7fff762b9680) at ./main.c:914
#42 0x000000000044c270 in main (argc=4, argv=0x7fff762b9788) at gdb.c:33
Comment 1 Jens Elmenthaler 2011-03-09 16:09:28 UTC
A couple of observations:

1) I altered StdStringPrinter to not retrieve more than 100 chars in its to_string methods, and I don't see any hangups any longer.

2) There is no hangup if I use gdb's command line instead of a graphical frontend. This is because the command line interface has a user setting for the number of characters to fetch for strings.

3) The hangup is not just limited to -stack-list-locals, it can be any MI command that tries to return the value of a local, an expression, or MI variable
Comment 2 Jens Elmenthaler 2011-03-09 16:16:09 UTC
Some thoughts on how to circumvent such hangups:

I don't think that pretty printers for strings should implement a limit on the max number of chars to fetch, this should be controlled by the frontend, as the gdb command line has its own user setting for the limit

This would lead to a MI command that lets the frontend adjust such a limit.
Comment 3 Phil Muldoon 2011-04-18 09:56:56 UTC
I gratuitously added a few people to this bug.  Apologies if you don't care/don't want to be CC'd.  I wanted a sample MI audience, vlad and tom to comment.  It seems to me that we will be forever plagued Python by pretty printers trying to interpret uninitialized data.  I think Jens idea is good.  We could add a --limit=100 optional flag to some MI commands and list this as a feature via the MI features mechanism.  What MI commands would need this?  Would we limit it by byte, or by (wide) char?
Comment 4 Andre' 2011-04-18 10:25:30 UTC
I think limiting the size per default makes sense, and 100 (whether wide or narrow does not matter) is probably not bad (Qt Creator uses 1000 for std::string, but that value is really not critical)
Comment 5 Phil Muldoon 2011-04-18 10:53:39 UTC
I don't think we should limit it by default.  As this would be an optional switch, the default would be unlimited.  But a way for FEs to actually instruct GDB/MI not to fetch any more than a sample is a good idea. Per command.  I'm guessing this would really only be used when a new frame/block is entered and the FE wants a representation of the variables in there without actually fetching (much of) the uninitialized data?

I hack on the Python side of GDB, and I don't know a tremendous amount of MI, and even less what MI consumers really want.  But this feature with Python GDB pretty-printers is a persistent pain.  What do you all want?
Comment 6 Andre' 2011-04-18 11:34:44 UTC
I still think having a default limit that leave gdb itself (and a frontend using it) in a usable state would make sense. 

Limiting the size of dumped data to something that finishes dumping in acceptable time (less than a few seconds in total, given the uncertain number of items to display a single display should be well under a second) seems to be a good first approximation at least as long as the data dumping is not interruptible (see 12615).

Anyway, if you think the frontend should be required to use --limit=100, so be it.

To the second issue: I don't think the assumption that data display can be sensibly steered by keeping track of entering and leaving stack frames or block scopes holds true. Both debugging itself and background activities might (and typically do) result in changed displays.
Comment 7 Marc Khouzam 2011-04-18 16:13:57 UTC
(In reply to comment #6)
> I still think having a default limit that leave gdb itself (and a frontend
> using it) in a usable state would make sense. 
> 
> Limiting the size of dumped data to something that finishes dumping in
> acceptable time (less than a few seconds in total, given the uncertain number
> of items to display a single display should be well under a second) seems to be
> a good first approximation at least as long as the data dumping is not
> interruptible (see 12615).
> 
> Anyway, if you think the frontend should be required to use --limit=100, so be
> it.
> 
> To the second issue: I don't think the assumption that data display can be
> sensibly steered by keeping track of entering and leaving stack frames or block
> scopes holds true. Both debugging itself and background activities might (and
> typically do) result in changed displays.

I agree with Andre.  Eclipse blindly asks GDB for values of variables and has no idea of a variable has been initialized or not.  Therefore, if adding --limit is the proper way to fix this issue, Eclipse will always use --limit; so, if a FE always uses a flag, it makes me think having a default would make sense.

BTW, thanks for dealing with this issue, PrettyPrinting is one of the very nice new features we are happy to make use of.
Comment 8 Tom Tromey 2011-11-10 21:34:18 UTC
Some kind of fetch limit makes sense to me.
It should not default to unlimited; that just makes naive clients die
when there is some kind of corruption.  Just make it big enough to cover
all normal uses -- 10K or something.
To be clear, I think the fetch limit should only apply to strings;
for varobjs with children we already have a limiting system in place.
Comment 9 Axel Müller 2013-07-04 19:51:34 UTC
Any progress here?