MI commands with --thread (--frame?) do not preserve user selected thread / frame

Simon Marchi simark@simark.ca
Wed Jun 19 15:54:00 GMT 2019


On 2019-06-19 11:10 a.m., Jan Vrany wrote:
> On Wed, 2019-06-19 at 11:53 +0100, Jan Vrany wrote:
>> Hi, 
>>
>> I was debugging a multithreaded program and realized that using --thread option to
>> verious MI command silently changes user selected thread - here's an example using
>> separate UI and CLI chahhel (tested on commit 6f5601c4d0)
>>
>>
> ...
>>
>>
>> As you can see, there was no `frame`, `thread`, `-select-frame` or `-thread-select` command between
>> first and second info thread / frame commands on CLI, yet the selected thread / frame changed (silently).
>>
>> Is this intended behavior? If so what's the rationale?

No, this is indeed a known bug:

https://sourceware.org/bugzilla/show_bug.cgi?id=20684

> Simple patch that preserves user selected context:
> 
> ---
> 
> diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
> index 13c310d494..ac3969f1b4 100644
> --- a/gdb/mi/mi-main.c
> +++ b/gdb/mi/mi-main.c
> @@ -2060,6 +2060,7 @@ mi_cmd_execute (struct mi_parse *parse)
>        set_current_program_space (inf->pspace);
>      }
>  
> +  gdb::optional<scoped_restore_current_thread> thread_saver;
>    if (parse->thread != -1)
>      {
>        thread_info *tp = find_thread_global_id (parse->thread);
> @@ -2070,9 +2071,11 @@ mi_cmd_execute (struct mi_parse *parse)
>        if (tp->state == THREAD_EXITED)
>         error (_("Thread id: %d has terminated"), parse->thread);
>  
> +      thread_saver.emplace ();
>        switch_to_thread (tp);
>      }
>  
> +  gdb::optional<scoped_restore_selected_frame> frame_saver;
>    if (parse->frame != -1)
>      {
>        struct frame_info *fid;
> @@ -2080,8 +2083,11 @@ mi_cmd_execute (struct mi_parse *parse)
>  
>        fid = find_relative_frame (get_current_frame (), &frame);
>        if (frame == 0)
> -       /* find_relative_frame was successful */
> -       select_frame (fid);
> +        {
> +          /* find_relative_frame was successful */
> +          frame_saver.emplace ();
> +          select_frame (fid);
> +        }
>        else
>         error (_("Invalid frame id: %d"), frame);
>      }
> 

This is what I get:

i th
&"i th\n"
~"  Id   Target Id                                          Frame \n"
~"* 1    Thread 0x7f792bce6e40 (LWP 4439) \"gnome-calculato\" 0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  2    Thread 0x7f791d00b700 (LWP 4441) \"gmain\"           0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  3    Thread 0x7f791c80a700 (LWP 4442) \"gdbus\"           0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  4    Thread 0x7f7917981700 (LWP 4443) \"dconf worker\"    0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
^done
(gdb)
-stack-info-depth --thread 3
^done,depth="7"
~"[Switching to thread 1 (Thread 0x7f792bce6e40 (LWP 4439))]\n"
~"#0  0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
=thread-selected,id="1",frame={level="0",addr="0x00007f7929316bf9",func="poll",args=[],from="/lib/x86_64-linux-gnu/libc.so.6",arch="i386:x86-64"}
(gdb)
i th
&"i th\n"
~"  Id   Target Id                                          Frame \n"
~"* 1    Thread 0x7f792bce6e40 (LWP 4439) \"gnome-calculato\" 0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  2    Thread 0x7f791d00b700 (LWP 4441) \"gmain\"           0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  3    Thread 0x7f791c80a700 (LWP 4442) \"gdbus\"           0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
~"  4    Thread 0x7f7917981700 (LWP 4443) \"dconf worker\"    0x00007f7929316bf9 in poll () from /lib/x86_64-linux-gnu/libc.so.6\n"
^done
(gdb)

So it seems to work (at least for a simple case, there might be some edge cases I don't recall).  I
think that the CLI and MI events about the thread change should not appear though, since the goal is
to make it appear as if there is no user selection changes.

Simon



More information about the Gdb mailing list