forked from Imagelibrary/binutils-gdb
After the "Always put inferiors in their own terminal/session [gdb/9425, gdb/14559]" change, when a user types "Ctrl-C" while the inferior is running, GDB is the one who gets the SIGINT, not the inferior process. GDB then forwards the SIGINT to the inferior with target_pass_ctrlc. That was necessary but not not sufficient to fix PRs gdb/9425, gdb/14559, because if a program blocks SIGINT with e.g. sigprocmask, then if GDB sends it a SIGINT, the signal isn't ever delivered to the process, so ptrace does not intercept it. You type Ctrl-C, but nothing happens. Similarly, if a program uses sigwait to wait for SIGINT, and the program receives a SIGINT, the SIGINT is _not_ intercepted by ptrace, it goes straight to the inferior. Now that the Ctrl-C results in a SIGINT sent to GDB instead of the inferior, we can make GDB interrupt the program any other way we like. This patch makes non-stop-capable ports interrupt the program with stop_all_threads / target_stop (i.e., SIGSTOP) instead of target_pass_ctrlc (i.e., SIGINT), which always works -- SIGSTOP can't be blocked/ignored. (In the future GDB may even switch to PTRACE_INTERRUPT on Linux, though that's a project of its own.) Another advantage here is with multi-target -- currently, because GDB relies on Ctrl-C stopping one thread, and then stopping all other threads in reaction to that stop, target_pass_ctrlc tries to find one inferior with a thread that is running, in any target. If the selected target for some reason fails to process the Ctrl-C request, then the Ctrl-C ends up lost. The mechanism implemented in this patch is different -- we never have to pick a thread, inferior or target -- we're going to stop everything, so we end up in stop_all_threads. For non-stop, the patch preserves the current behavior of only stopping one thread in reaction to Ctrl-C, so it can still happen that the thread that GDB selects to stop disappears and the Ctrl-C ends up being lost. However, because now GDB always sees the SIGINT first, we can change how Ctrl-C behaves there too. We could even make it configurable -- for example, it could be reasonable that Ctrl-C simply drops the CLI back to the prompt, without stopping anything at all. That might be interesting for "set observer-mode on", at least. This commit has a user-visible behavior change in all-stop mode -- when you interrupt the program with Ctrl-C, instead of: Thread 1 "threads" received signal SIGINT, Interrupt. You'll get: Thread 1 "threads" stopped. Which is what you already got with the "interrupt" command in non-stop mode. If you really want to pass a SIGINT to the program, you can then issue: (gdb) signal SIGINT This commit also adjusts the testsuite to cope with that output alternative. With this change, the gdb.base/sigint-sigwait.exp and gdb.base/sigint-masked-out.exp testcases now pass cleanly on GNU/Linux, on both native debugging and gdbserver + "maint set target-non-stop on", so the kfails are adjusted accordingly. gdb/ChangeLog: yyyy-mm-dd Pedro Alves <pedro@palves.net> PR gdb/9425 PR gdb/14559 * event-top.c (default_quit_handler): Mark infrun event-loop handler with mark_infrun_async_event_handler_ctrl_c instead of passing the Ctrl-C to the target directly with target_pass_ctrlc. * infcmd.c (interrupt_target_1): On non-stop targets, Mark infrun event-loop handler with mark_infrun_async_event_handler_interrupt_all instead of using target_interrupt. * infrun.c (interrupt_all_requested, switch_to_stop_thread) (sync_interrupt_all) (mark_infrun_async_event_handler_interrupt_all) (mark_infrun_async_event_handler_ctrl_c): New. (infrun_async_inferior_event_handler): Handle Ctrl-C/interrupt requests. * infrun.h (mark_infrun_async_event_handler_interrupt_all) (mark_infrun_async_event_handler_ctrl_c): Declare. * linux-nat.c (wait_for_signal): Don't handle Ctrl-C here. (linux_nat_wait_1): Handle it here, by marking the infrun event handler, and returning TARGET_WAITKIND_IGNORE with the quit flag still set. * target.c (maybe_pass_ctrlc): New. (target_terminal::inferior, target_terminal::restore_inferior): Use it. (target_pass_ctrlc): Ass there's no non-stop target pushed. gdb/testsuite/ChangeLog: yyyy-mm-dd Pedro Alves <pedro@palves.net> PR gdb/9425 PR gdb/14559 * gdb.base/bp-cmds-continue-ctrl-c.exp: Expect "stopped" in alternative to "signal SIGINT". * gdb.base/interrupt-daemon-attach.exp: Likewise. * gdb.base/interrupt-daemon.exp: Likewise. * gdb.base/interrupt-noterm.exp: Likewise. * gdb.base/interrupt.exp: Likewise. * gdb.base/random-signal.exp: Likewise. * gdb.base/range-stepping.exp: Likewise. * gdb.gdb/selftest.exp: Likewise. * gdb.mi/new-ui-mi-sync.exp: Likewise. * gdb.multi/multi-target-interrupt.exp: Likewise. * gdb.multi/multi-target-no-resumed.exp: Likewise. * gdb.multi/multi-term-settings.exp: Likewise. * gdb.server/reconnect-ctrl-c.exp: Likewise. * gdb.threads/async.exp: Likewise. * gdb.threads/continue-pending-status.exp: Likewise. * gdb.threads/leader-exit.exp: Likewise. * gdb.threads/manythreads.exp: Likewise. * gdb.threads/pthreads.exp: Likewise. * gdb.threads/schedlock.exp: Likewise. * gdb.threads/sigthread.exp: Likewise. * lib/gdb.exp (can_interrupt_blocked_sigint): New. * gdb.base/sigint-masked-out.exp (test_ctrl_c) (test_interrupt_cmd): Use can_interrupt_blocked_sigint, and don't kfail if true. * gdb.base/sigint-sigwait.exp (test_ctrl_c, test_interrupt_cmd): Likewise. Change-Id: I83c1b6a20deea1f1909156adde1d60b8f6f2629b
114 lines
2.5 KiB
Plaintext
114 lines
2.5 KiB
Plaintext
# Copyright 2021 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/>.
|
|
|
|
# Make sure that we can interrupt an inferior that has all signals
|
|
# masked out, including SIGINT, and then waits for signals with
|
|
# sigwait. Test interrupting with both Ctrl-C and the "interrupt"
|
|
# command.
|
|
|
|
standard_testfile
|
|
|
|
if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
|
|
return -1
|
|
}
|
|
|
|
# Test interrupting with Ctrl-C.
|
|
|
|
proc_with_prefix test_ctrl_c {} {
|
|
global binfile
|
|
global gdb_prompt
|
|
|
|
clean_restart $binfile
|
|
|
|
if ![runto "done"] {
|
|
fail "can't run to done function"
|
|
return
|
|
}
|
|
|
|
set can_interrupt [can_interrupt_blocked_sigint]
|
|
|
|
gdb_test_multiple "continue" "" {
|
|
-re "Continuing" {
|
|
pass $gdb_test_name
|
|
}
|
|
}
|
|
|
|
after 200
|
|
|
|
send_gdb "\003"
|
|
|
|
global exited_normally_re
|
|
|
|
gdb_test_multiple "" "ctrl-c stops process" {
|
|
-re -wrap "(received signal SIGINT|stopped).*" {
|
|
pass $gdb_test_name
|
|
}
|
|
-re -wrap "Inferior.*exited normally.*" {
|
|
if {!$can_interrupt} {
|
|
setup_kfail "gdb/9425" *-*-*
|
|
}
|
|
fail "$gdb_test_name (the program exited)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Test interrupting with the "interrupt" command.
|
|
|
|
proc_with_prefix test_interrupt_cmd {} {
|
|
global binfile
|
|
global gdb_prompt
|
|
|
|
clean_restart $binfile
|
|
|
|
if ![runto "done"] {
|
|
fail "can't run to done function"
|
|
return
|
|
}
|
|
|
|
set can_interrupt [can_interrupt_blocked_sigint]
|
|
|
|
gdb_test_multiple "continue&" "" {
|
|
-re "Continuing\\.\r\n$gdb_prompt " {
|
|
pass $gdb_test_name
|
|
}
|
|
}
|
|
|
|
after 200
|
|
|
|
gdb_test_multiple "interrupt" "" {
|
|
-re "$gdb_prompt " {
|
|
pass $gdb_test_name
|
|
}
|
|
}
|
|
|
|
global exited_normally_re
|
|
|
|
gdb_test_multiple "" "interrupt cmd stops process" {
|
|
-timeout 5
|
|
-re "(received signal SIGINT|stopped)" {
|
|
pass $gdb_test_name
|
|
}
|
|
-re "Inferior.*exited normally" {
|
|
if {!$can_interrupt} {
|
|
setup_kfail "gdb/14559" *-*-*
|
|
}
|
|
fail "$gdb_test_name (the program exited)"
|
|
}
|
|
}
|
|
}
|
|
|
|
test_ctrl_c
|
|
test_interrupt_cmd
|