[PATCH] gdb/infrun: disable pagination in fetch_inferior_event

Pedro Alves pedro@palves.net
Thu Oct 29 19:14:03 GMT 2020


On 10/14/20 11:24 AM, Tankut Baris Aktemur via Gdb-patches wrote:
> Having pagination enabled when handling an inferior event gives the
> user an option to quit, which causes early exit in GDB's flow and may
> lead to half-baked state.  For instance, here is a case where we quit
> in the middle of handling an inferior exit:
> 
>   $ gdb ./a.out
>   Reading symbols from ./a.out...
>   (gdb) set height 2
>   (gdb) run
>   Starting program: ./a.out
>   --Type <RET> for more, q to quit, c to continue without paging--q
>   Quit
>   Couldn't get registers: No such process.
>   (gdb) set height unlimited
>   Couldn't get registers: No such process.
>   (gdb) info threads
>     Id   Target Id         Frame
>   * 1    process 27098     Couldn't get registers: No such process.
>   Couldn't get registers: No such process.
>   (gdb)
> 
> Or suppose having a multi-threaded program like below:
> 
>   static void *
>   fun (void *dummy)
>   {
>     int a = 1; /* break-here */
>     return NULL;
>   }
> 
>   int
>   main (void)
>   {
>     pthread_t thread;
>     pthread_create (&thread, NULL, fun, NULL);
>     pthread_join (thread, NULL);
> 
>     return 0;
>   }
> 
> If we define a breakpoint at line "break-here", we expect only Thread
> 2 to hit it.
> 
>   $ gdb ./a.out
>   Reading symbols from ./a.out...
>   (gdb) break 7
>   Breakpoint 1 at 0x1182: file mt.c, line 7.
>   (gdb) set height 2
>   (gdb) run
>   Starting program: ./a.out
>   [Thread debugging using libthread_db enabled]
>   Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
>   [New Thread 0x7ffff77c4700 (LWP 23048)]
>   --Type <RET> for more, q to quit, c to continue without paging--q
>   Quit
>   (gdb) set height unlimited
>   (gdb) info thread
>     Id   Target Id                                 Frame
>   * 1    Thread 0x7ffff7fe3740 (LWP 23044) "a.out" 0x00007ffff7bbed2d in ...
>     2    Thread 0x7ffff77c4700 (LWP 23048) "a.out" fun (dummy=0x0) at mt.c:7
>   (gdb)
> 
> The prompt for continuation was triggered because Thread 2 hit the
> breakpoint.  (If we had hit 'c', we were going to see that stop event,
> but we didn't.)  The context did not switch to Thread 2.  GDB also did
> not execute several other things it would normally do in
> infrun.c:normal_stop after outputting "[Switching to Thread ...]" (but
> it seems harmless in this case).  If we 'continue' at this state, both
> threads run until termination, and we don't see the breakpoint hit
> event ever.
> 
> Here is another related and more complicated scenario that leads to a
> GDB crash.  Create two inferiors, one sitting on top of a native
> target, and the other on a remote target, so that we have a
> multi-target setting, like so:
> 
>   (gdb) i inferiors
>     Num  Description       Connection     Executable
>     1    process 13786     1 (native)     a.out
>   * 2    process 13806     2 (remote ...) target:a.out
> 
> Next, resume both inferiors to run until termination:
> 
>   (gdb) set schedule-multiple on
>   (gdb) set height 2
>   (gdb) continue
>   Continuing.
>   --Type <RET> for more, q to quit, c to continue without paging--[Inferior 2 (process 13806) exited normally]
> 
>   terminate called after throwing an instance of 'gdb_exception_error'
>   Aborted
> 
> Here, GDB first received a termination event from Inferior 1.  GDB
> attempted to print this event, triggering a "prompt for continue", and
> GDB started polling for events, hoping to get an input from the user.
> However, the exit event from Inferior 2 was received instead.  So, GDB
> started processing an exit event while being in the middle of
> processing another exit event.  It was not ready for this situation
> and eventually crashed.
> 
> To address these cases, temporarily disable pagination in
> fetch_inferior_event.  This doesn't affect commands like 'info
> threads', 'backtrace', or 'thread apply'.
> 

I agree with this.  

I did something similar in the context of the new-ui work a few years
back, because pagination doesn't work properly in that scenario -- if an
event causes a pagination prompt in the CLI UI, then the MI UI stops
responding.

I came to the realization that we don't really want pagination in reaction
to target events.  Or any query, for the matter.

Not great to leave your program running to catch some bug that takes
a while to trigger, and then find the program paused for a pagination
or query.

> diff --git a/gdb/testsuite/gdb.base/double-prompt-target-event-error.exp b/gdb/testsuite/gdb.base/double-prompt-target-event-error.exp
> deleted file mode 100644
> index 459d1866f32..00000000000
> --- a/gdb/testsuite/gdb.base/double-prompt-target-event-error.exp
> +++ /dev/null
> @@ -1,122 +0,0 @@
> -# Copyright (C) 2014-2020 Free Software Foundation, Inc.
> -
> -# This program is free software; you can redistribute it and/or modify
> -# it under the terms of the GNU General Public License as published by
> -# the Free Software Foundation; either version 3 of the License, or
> -# (at your option) any later version.
> -#
> -# This program is distributed in the hope that it will be useful,
> -# but WITHOUT ANY WARRANTY; without even the implied warranty of
> -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -# GNU General Public License for more details.
> -#
> -# You should have received a copy of the GNU General Public License
> -# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> -
> -if [target_info exists gdb,nointerrupts] {
> -    verbose "Skipping double-prompt-target-event-error.exp because of nointerrupts."
> -    return
> -}
> -
> -standard_testfile
> -
> -if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug] == -1} {
> -    return -1
> -}
> -
> -# Test throwing an error while GDB is handling a target event.  We use
> -# a ctrl-c/quit in a pagination prompt to emulate an error.  COMMAND
> -# is either "continue" or "wrapcont".  The latter is a continue issued
> -# from a user-defined command.  That exercises the case of the
> -# interpreter forced sync, which was the case that originally had a
> -# bug.
> -

It sounds like here we're losing some coverage here, where the pagination
was only used as a proxy for an error.  I can't think of how to test
the original bug in a different way, though...

So...  OK as is.


More information about the Gdb-patches mailing list