Files
binutils-gdb/gdb/testsuite/gdb.base/help.exp
Andrew Burgess 29f7ef927a gdb: add timeouts for inferior function calls
In the previous commits I have been working on improving inferior
function call support.  One thing that worries me about using inferior
function calls from a conditional breakpoint is: what happens if the
inferior function call fails?

If the failure is obvious, e.g. the thread performing the call
crashes, or hits a breakpoint, then this case is already well handled,
and the error is reported to the user.

But what if the thread performing the inferior call just deadlocks?
If the user made the call from a 'print' or 'call' command, then the
user might have some expectation of when the function call should
complete, and, when this time limit is exceeded, the user
will (hopefully) interrupt GDB and regain control of the debug
session.

But, when the inferior function call is from a breakpoint condition it
is much harder to understand that GDB is deadlocked within an inferior
call.  Maybe the breakpoint hasn't been hit yet?  Or maybe the
condition was always false?  Or maybe GDB is deadlocked in an inferior
call?  The only way to know for sure is for the user to periodically
interrupt the inferior, check on the state of all the threads, and
then continue.

Additionally, the focus of the previous commit was inferior function
calls, from a conditional breakpoint, in a multi-threaded inferior.
This opens up a whole new set of potential failure conditions.  For
example, what if the function called relies on interaction with some
other thread, and the other thread crashes?  Or hits a breakpoint?
Given how inferior function calls work (in a synchronous manner), a
stop event in some other thread is going to be ignored while the
inferior function call is being executed as part of a breakpoint
condition, and this means that GDB could get stuck waiting for the
original condition thread, which will now never complete.

In this commit I propose a solution to this problem.  A timeout.  For
targets that support async-mode we can install an event-loop timer
before starting the inferior function call.  When the timer expires we
will stop the thread performing the inferior function call.  With this
mechanism in place a user can be sure that any inferior call they make
will either complete, or timeout eventually.

Adding a timer like this is obviously a change in behaviour for the
more common 'call' and 'print' uses of inferior function calls, so, in
this patch, I propose having two different timers.  One I call the
'direct-call-timeout', which is used for 'call' and 'print' commands.
This timeout is by default set to unlimited, which, not surprisingly,
means there is no timeout in place.

A second timer, which I've called 'indirect-call-timeout', is used for
inferior function calls from breakpoint conditions.  This timeout has
a default value of 30 seconds.  This is a reasonably long time to
wait, and hopefully should be enough in most cases to allow the
inferior call to complete.  An inferior call that takes more than 30
seconds, which is installed on a breakpoint condition is really going
to slow down the debug session, so hopefully this is not a common use
case.

The user is, of course, free to reduce, or increase the timeout value,
and can always use Ctrl-c to interrupt an inferior function call, but
this timeout will ensure that GDB will stop at some point.

The new commands added by this commit are:

  set direct-call-timeout SECONDS
  show direct-call-timeout
  set indirect-call-timeout SECONDS
  show indirect-call-timeout

These new timeouts do depend on async-mode, so, if async-mode is
disabled (maint set target-async off), or not supported (e.g. target
sim), then the timeout is treated as unlimited (that is, no timeout is
set).

For targets that "fake" non-async mode, e.g. Linux native, where
non-async mode is really just async mode, but then we park the target
in a sissuspend, we could easily fix things so that the timeouts still
work, however, for targets that really are not async aware, like the
simulator, fixing things so that timeouts work correctly would be a
much bigger task - that effort would be better spent just making the
target async-aware.  And so, I'm happy for now that this feature will
only work on async targets.

The two new show commands will display slightly different text if the
current target is a non-async target, which should allow users to
understand what's going on.

There's a somewhat random test adjustment needed in gdb.base/help.exp,
the test uses a regexp with the apropos command, and expects to find a
single result.  Turns out the new settings I added also matched the
regexp, which broke the test.  I've updated the regexp a little to
exclude my new settings.

Reviewed-By: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Tested-By: Luis Machado <luis.machado@arm.com>
Tested-By: Keith Seitz <keiths@redhat.com>
2024-03-25 17:25:06 +00:00

177 lines
8.4 KiB
Plaintext

# Copyright 1988-2024 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/>.
# This file was written by Rob Savoye. (rob@cygnus.com)
# Test basic help functionality.
# This is not intended to test the help text of every command,
# or even more than a few commands - too much of a maintenance burden.
gdb_start
# Disable pagination.
gdb_test_no_output "set height 0" "disable pagination"
# Test all the help classes.
test_class_help "aliases" {"User-defined aliases of other commands\.\[\r\n\]+"}
test_class_help "breakpoints" {
"Making program stop at certain points\.\[\r\n\]+"
}
with_read1_timeout_factor 10 {
test_class_help "data" {"Examining data\.\[\r\n\]+"}
test_class_help "files" {"Specifying and examining files\.\[\r\n\]+"}
test_class_help "internals" {
"Maintenance commands\.\[\r\n\]+"
"Some gdb commands are provided just for use by gdb maintainers\.\[\r\n\]+"
"These commands are subject to frequent change, and may not be as\[\r\n\]+"
"well documented as user commands\.\[\r\n\]+"
}
}
test_class_help "obscure" {"Obscure features\.\[\r\n\]+"}
test_class_help "running" {"Running the program\.\[\r\n\]+"}
test_class_help "stack" {
"Examining the stack\..*\[\r\n\]+"
"When the program being debugged stops, gdb selects the innermost frame\.\[\r\n\]+"
"The commands below can be used to select other frames by number or address\.\[\r\n\]+"
}
with_read1_timeout_factor 10 {
test_class_help "status" {
"Status inquiries\.\[\r\n\]+"
}
test_class_help "support" {"Support facilities\.\[\r\n\]+"}
test_class_help "tracepoints" {
"Tracing of program execution without stopping the program\.\[\r\n\]+"
}
}
with_read1_timeout_factor 10 {
test_user_defined_class_help
# Test help of an abbreviated command. "break" is picked at random.
set help_breakpoint_text "Set breakpoint at specified location\..*"
# Test help breakpoint "b" abbreviation.
gdb_test "help b" $help_breakpoint_text "help breakpoint \"b\" abbreviation"
# Test help breakpoint "br" abbreviation.
gdb_test "help br" $help_breakpoint_text "help breakpoint \"br\" abbreviation"
# Test help breakpoint "bre" abbreviation;
gdb_test "help bre" $help_breakpoint_text "help breakpoint \"bre\" abbreviation"
# Test help breakpoint "brea" abbreviation.
}
gdb_test "help brea" $help_breakpoint_text "help breakpoint \"brea\" abbreviation"
# Test help breakpoint "break" abbreviation.
gdb_test "help break" $help_breakpoint_text "help breakpoint \"break\" abbreviation"
# Test help of an aliased command. "bt" is picked at random.
set help_backtrace_text "Print backtrace of all stack frames, or innermost COUNT frames\..*"
# Test help backtrace "bt" abbreviation.
gdb_test "help bt" $help_backtrace_text "help backtrace \"bt\" abbreviation"
# Test help backtrace.
gdb_test "help backtrace" $help_backtrace_text
# Test help commands.
gdb_test "help commands" "Set commands to be executed when the given breakpoints are hit\.\[\r\n\]+Give a space-separated breakpoint list as argument after \"commands\"\.\[\r\n\]+A list element can be a breakpoint number \\(e.g. `5'\\) or a range of numbers\[\r\n\]+\\(e.g. `5-7'\\)\.\[\r\n\]+With no argument, the targeted breakpoint is the last one set\.\[\r\n\]+The commands themselves follow starting on the next line\.\[\r\n\]+Type a line containing \"end\" to indicate the end of them\.\[\r\n\]+Give \"silent\" as the first line to make the breakpoint silent;\[\r\n\]+then no output is printed when it is hit, except what the commands print\."
# Test a prefix command. "delete" is picked at random.
# Test help delete "d" abbreviation.
set expected_help_delete {
"Delete all or some breakpoints\.\[\r\n\]+"
"Usage: delete \\\[BREAKPOINTNUM\\\]...\[\r\n\]+"
"Arguments are breakpoint numbers with spaces in between\.\[\r\n\]+"
"To delete all breakpoints, watchpoints, tracepoints, and catchpoints,\.\[\r\n\]+"
"give no argument\.\[\r\n\]+"
"Also a prefix command for deletion of other GDB objects\.\[\r\n\]+"
}
test_prefix_command_help {"d" "delete"} $expected_help_delete "help delete \"d\" abbreviation"
# Test help delete.
test_prefix_command_help "delete" $expected_help_delete
# Make sure help for help itself is present.
# Test help help "h" abbreviation.
gdb_test "help h" "Print list of commands\." "help help \"h\" abbreviation"
# Test help help.
gdb_test "help help" "Print list of commands\."
# The startup banner refers to "show copying" and "show warranty",
# might as well test for them.
# Test help info copying.
gdb_test "help show copying" "Conditions for redistributing copies of GDB\."
# Test help info warranty.
gdb_test "help show warranty" "Various kinds of warranty you do not have\."
# Test a few other random "help show" commands.
# Test help show commands.
gdb_test "help show commands" "Show the history of commands you typed\.\[\r\n\]+You can supply a command number to start with, or a `\[+\]' to start after\[\r\n\]+the previous command number shown\."
# Test help show confirm.
gdb_test "help show confirm" "Show whether to confirm potentially dangerous operations\."
# Test help info bogus-gdb-command.
gdb_test "help info bogus-gdb-command" "Undefined info command: \"bogus-gdb-command\"\. Try \"help info\"\."
# Test help gotcha.
gdb_test "help gotcha" "Undefined command: \"gotcha\"\. Try \"help\"\."
# Test apropos regex.
gdb_test "apropos \\\(print\[\^\[ bsiedf\\\"'.-\]\\\)" "handle -- Specify how to handle signals\."
# Test apropos >1 word string.
gdb_test "apropos handle signal" "handle -- Specify how to handle signals\."
# Test apropos apropos.
gdb_test "apropos apropos" "apropos -- Search for commands matching a REGEXP.*"
# Test apropos for commands having aliases.
gdb_test_no_output "alias mybt = backtrace" "define mybt alias"
gdb_test_no_output "alias mybt10 = backtrace 10" "define mybt10 alias"
gdb_test "apropos Print backtrace of all stack frames, or innermost COUNT frames\." \
"backtrace, mybt10, mybt, where, bt -- Print backtrace of all stack frames, or innermost COUNT frames\.\[\r\n\]+ alias mybt10 = backtrace 10"
# Test help for commands having aliases.
gdb_test "help bt" "backtrace, mybt10, mybt, where, bt\[\r\n\]+ alias mybt10 = backtrace 10\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*"
# Document the aliases. The apropos and help commands should then consider them
# as "standalone" commands.
gdb_test_multiple "document mybt" "document alias: mybt" {
-re "Type documentation for \"mybt\".\r\nEnd with a line saying just \"end\".\r\n>$" {
gdb_test "An alias of command backtrace without any args.\nend" \
"" \
"document alias: mybt"
}
}
gdb_test_multiple "document mybt10" "document alias: mybt10" {
-re "Type documentation for \"mybt10\".\r\nEnd with a line saying just \"end\".\r\n>$" {
gdb_test "An alias of command backtrace with arg 10.\nend" \
"" \
"document alias: mybt10"
}
}
# As the aliases are now documented, they do not appear in apropos/help backtrace output anymore.
gdb_test "apropos Print backtrace of all stack frames, or innermost COUNT frames\." \
"backtrace, where, bt -- Print backtrace of all stack frames, or innermost COUNT frames\." \
"apropos after documenting aliases"
gdb_test "help bt" "backtrace, where, bt\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*" \
"help after documenting aliases"
# Check apropos and help use the alias documentation.
gdb_test "apropos An alias of command backtrace with arg 10" \
"mybt10 -- An alias of command backtrace with arg 10\." \
"apropos after documenting aliases showing mybt10 doc"
gdb_test "help mybt" " alias mybt = backtrace \[\r\n\]+An alias of command backtrace without any args\." \
"help mybt after documenting aliases showing mybt doc"
# Check pre-defined aliases cannot be documented.
gdb_test "document where" "Alias \"where\" is built-in.*" \
"documenting builtin where alias disallowed"