old-cross-binutils/gdb/testsuite/gdb.server/connect-stopped-target.c

23 lines
786 B
C
Raw Normal View History

remote non-stop: Process initially stopped threads before other commands The main motivation for this is making non-stop / all-stop behave similarly on initial connection, in order to move in the direction of reimplementing all-stop mode with the remote target always running in non-stop mode. When we connect to a remote target in non-stop mode, we may find threads either running or already stopped. The act of connecting itself does not force threads to stop. To handle that, the remote non-stop connection is currently roughly like this: #1 - Fetch list of remote threads (qXfer:threads:read, qfThreadInfo, etc). All threads are assumed to be running until the target reports an asynchronous stop reply for them. #2 - Fetch the initial set of threads that were already stopped, with the '?' packet. (In non-stop, this is coupled with the vStopped mechanism to be able to retrieve the status of more than one thread.) The stop replies fetched in #2 are placed in the pending stop reply queue, and left for the regular event loop to process. That is, "target remote" finishes and returns _before_ those stops are processed. That means that it's possible to have GDB process further commands before the initial set of stopped threads is reported to the user. E.g., before the patch, note how the prompt is printed before the frame: Remote debugging using :9999 (gdb) [Thread 15296] #1 stopped. 0x0000003615a011f0 in ?? () Even though thread #1 was not running, for a moment, the user can see it as such: $ gdb a.out -ex "set non-stop 1" -ex "tar rem :9999" -ex "info threads" -ex "info registers" Remote debugging using :9999 Id Target Id Frame * 1 Thread 4772 (running) Target is executing. <<<<<<< info registers (gdb) [Thread 4772] #1 stopped. 0x0000003615a011f0 in ?? () To fix that, this commit makes gdb process all threads found already stopped at connection time, before giving the prompt to the user. The fix takes a cue from fork-child.c:startup_inferior [1], and processes the events locally in remote.c, avoiding the whole wait_for_inferior/handle_inferior_event path. I decided to try this approach after noticing that: - several cases in handle_inferior_event miss checking stop_soon. - we don't want to fetch the thread list in normal_stop. and trying to fix them was resulting in sprinkling stop_soon checks in many places, and uglifying normal_stop even more. While with this patch, I'm avoiding changing GDB's output other than when the prompt is printed, I think this approach is more flexible if we do want to change it. And also, it's likely easier to get rid of the MI *running event that is still sent for threads that are initially found stopped, if we want to. This happens to fix the testsuite too. All non-stop tests are racy against "target remote" / gdbserver testing currently. That is, sometimes the tests run, but other times they're just skipped without any indication of PASS/FAIL. When that happens, the logs show: target remote localhost:2346 Remote debugging using localhost:2346 (gdb) [Thread 25418] #1 stopped. 0x0000003615a011f0 in ?? () ^CQuit (gdb) Remote debugging from host 127.0.0.1 Killing process(es): 25418 monitor exit (gdb) Remote connection closed (gdb) testcase /home/pedro/gdb/mygit/build/../src/gdb/testsuite/gdb.threads/multi-create-ns-info-thr.exp completed in 61 seconds The trouble here is that there's output after the prompt, and the regex in question doesn't expect that: -re "Remote debugging using .*$serialport_re.*$gdb_prompt $" { verbose "Set target to $targetname" return 0 } [1] - before startup_inferior was added, we'd go through wait_for_inferior/handle_inferior_event while going through the shell, and that turned out problematic. Tested on x86_64 Fedora 20, gdbserver. gdb/ChangeLog: 2015-08-20 Pedro Alves <palves@redhat.com> * infrun.c (print_target_wait_results): Make extern. * infrun.h (print_target_wait_results): Declare. * remote.c (set_stop_requested_callback): Delete. (process_initial_stop_replies): New function. (remote_start_remote): Use it. (stop_reply_queue_length): New function. gdb/testsuite/ChangeLog: 2015-08-20 Pedro Alves <palves@redhat.com> * gdb.server/connect-stopped-target.c: New file. * gdb.server/connect-stopped-target.exp: New file.
2015-08-20 17:27:55 +00:00
/* This testcase is part of GDB, the GNU debugger.
Copyright 2015-2016 Free Software Foundation, Inc.
remote non-stop: Process initially stopped threads before other commands The main motivation for this is making non-stop / all-stop behave similarly on initial connection, in order to move in the direction of reimplementing all-stop mode with the remote target always running in non-stop mode. When we connect to a remote target in non-stop mode, we may find threads either running or already stopped. The act of connecting itself does not force threads to stop. To handle that, the remote non-stop connection is currently roughly like this: #1 - Fetch list of remote threads (qXfer:threads:read, qfThreadInfo, etc). All threads are assumed to be running until the target reports an asynchronous stop reply for them. #2 - Fetch the initial set of threads that were already stopped, with the '?' packet. (In non-stop, this is coupled with the vStopped mechanism to be able to retrieve the status of more than one thread.) The stop replies fetched in #2 are placed in the pending stop reply queue, and left for the regular event loop to process. That is, "target remote" finishes and returns _before_ those stops are processed. That means that it's possible to have GDB process further commands before the initial set of stopped threads is reported to the user. E.g., before the patch, note how the prompt is printed before the frame: Remote debugging using :9999 (gdb) [Thread 15296] #1 stopped. 0x0000003615a011f0 in ?? () Even though thread #1 was not running, for a moment, the user can see it as such: $ gdb a.out -ex "set non-stop 1" -ex "tar rem :9999" -ex "info threads" -ex "info registers" Remote debugging using :9999 Id Target Id Frame * 1 Thread 4772 (running) Target is executing. <<<<<<< info registers (gdb) [Thread 4772] #1 stopped. 0x0000003615a011f0 in ?? () To fix that, this commit makes gdb process all threads found already stopped at connection time, before giving the prompt to the user. The fix takes a cue from fork-child.c:startup_inferior [1], and processes the events locally in remote.c, avoiding the whole wait_for_inferior/handle_inferior_event path. I decided to try this approach after noticing that: - several cases in handle_inferior_event miss checking stop_soon. - we don't want to fetch the thread list in normal_stop. and trying to fix them was resulting in sprinkling stop_soon checks in many places, and uglifying normal_stop even more. While with this patch, I'm avoiding changing GDB's output other than when the prompt is printed, I think this approach is more flexible if we do want to change it. And also, it's likely easier to get rid of the MI *running event that is still sent for threads that are initially found stopped, if we want to. This happens to fix the testsuite too. All non-stop tests are racy against "target remote" / gdbserver testing currently. That is, sometimes the tests run, but other times they're just skipped without any indication of PASS/FAIL. When that happens, the logs show: target remote localhost:2346 Remote debugging using localhost:2346 (gdb) [Thread 25418] #1 stopped. 0x0000003615a011f0 in ?? () ^CQuit (gdb) Remote debugging from host 127.0.0.1 Killing process(es): 25418 monitor exit (gdb) Remote connection closed (gdb) testcase /home/pedro/gdb/mygit/build/../src/gdb/testsuite/gdb.threads/multi-create-ns-info-thr.exp completed in 61 seconds The trouble here is that there's output after the prompt, and the regex in question doesn't expect that: -re "Remote debugging using .*$serialport_re.*$gdb_prompt $" { verbose "Set target to $targetname" return 0 } [1] - before startup_inferior was added, we'd go through wait_for_inferior/handle_inferior_event while going through the shell, and that turned out problematic. Tested on x86_64 Fedora 20, gdbserver. gdb/ChangeLog: 2015-08-20 Pedro Alves <palves@redhat.com> * infrun.c (print_target_wait_results): Make extern. * infrun.h (print_target_wait_results): Declare. * remote.c (set_stop_requested_callback): Delete. (process_initial_stop_replies): New function. (remote_start_remote): Use it. (stop_reply_queue_length): New function. gdb/testsuite/ChangeLog: 2015-08-20 Pedro Alves <palves@redhat.com> * gdb.server/connect-stopped-target.c: New file. * gdb.server/connect-stopped-target.exp: New file.
2015-08-20 17:27:55 +00:00
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/>. */
int
main (void)
{
return 0;
}