mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-23 13:21:43 +08:00
The following scenario hangs: - maint set target-non-stop on - `gdbserver --attach` - a multi-threaded program For example: Terminal 1: $ gnome-calculator& [1] 495731 $ ../gdbserver/gdbserver --once --attach :1234 495731 Attached; pid = 495731 Listening on port 1234 Terminal 2: $ ./gdb -nx -q --data-directory=data-directory /usr/bin/gnome-calculator -ex "maint set target-non-stop on" -ex "tar rem :1234" Reading symbols from /usr/bin/gnome-calculator... (No debugging symbols found in /usr/bin/gnome-calculator) Remote debugging using :1234 * hangs * What happens is: - The protocol between gdb and gdbserver is in non-stop mode, but the user-visible behavior is all-stop - On connect, gdbserver sends one stop reply for one thread that is stops, the others stay running - In process_initial_stop_replies, gdb calls stop_all_threads to stop these other threads, because we are using the all-stop user-visible mode - stop_all_threads sends a stop request for all the running threads and then waits for resulting events - At this point, the remote target is in target_async(0) mode, which makes stop_all_threads not consider it for events - stop_all_threads loops indefinitely (it does not even block indefinitely, it is in an infinite busy loop) because there are no event sources. wait_one_event returns a TARGET_WAITKIND_NO_RESUMED wait status. Fix that by making the remote target async around the stop_all_threads call. I haven't implemented it because I'm not sure how to do it, but I think it would be a good idea to have, in stop_all_threads / wait_one / handle_one, an assert to check that if we are expecting one or more event, then there are some targets that are in a state where they can supply some events. Otherwise, we'll necessarily be stuck in this infinite loop, and it's probably due to a bug in GDB. I'm not too sure where to put this or how to express it though. Perhaps in stop_all_threads, here: for (int i = 0; i < waits_needed; i++) { wait_one_event event = wait_one (); *here* if (handle_one (event)) break; } If at that point, the returned event is TARGET_WAITKIND_NO_RESUMED, there's a problem. We expect some event, because we've asked some threads to stop, but all targets are answering that they won't have any events for us. That's a contradiction, and a sign that something has gone wrong. It could perhaps event be: gdb_assert (event.ws.kind != TARGET_WAITKIND_NO_RESUMED); in handle_one, as the idea is the same in prepare_for_detach. A bit more sophisticated would be: we know which targets we are expecting waits from, since we know which threads we have asked to stop. So if any of these targets returns TARGET_WAITKIND_NO_RESUMED, something is fishy. Add a test that tests attaching with gdbserver's --attach flag to a multi-threaded program, and then connecting to it. Without the fix, the test reproduces the hang. Change-Id: If6f6690a4887ca66693ef1af64791dda4c65f24f |
||
---|---|---|
bfd | ||
binutils | ||
config | ||
contrib | ||
cpu | ||
elfcpp | ||
etc | ||
gas | ||
gdb | ||
gdbserver | ||
gdbsupport | ||
gnulib | ||
gold | ||
gprof | ||
include | ||
intl | ||
ld | ||
libbacktrace | ||
libctf | ||
libdecnumber | ||
libiberty | ||
opcodes | ||
readline | ||
sim | ||
texinfo | ||
zlib | ||
.cvsignore | ||
.gitattributes | ||
.gitignore | ||
ar-lib | ||
ChangeLog | ||
compile | ||
config-ml.in | ||
config.guess | ||
config.rpath | ||
config.sub | ||
configure | ||
configure.ac | ||
COPYING | ||
COPYING3 | ||
COPYING3.LIB | ||
COPYING.LIB | ||
COPYING.LIBGLOSS | ||
COPYING.NEWLIB | ||
depcomp | ||
djunpack.bat | ||
install-sh | ||
libtool.m4 | ||
lt~obsolete.m4 | ||
ltgcc.m4 | ||
ltmain.sh | ||
ltoptions.m4 | ||
ltsugar.m4 | ||
ltversion.m4 | ||
MAINTAINERS | ||
Makefile.def | ||
Makefile.in | ||
Makefile.tpl | ||
makefile.vms | ||
missing | ||
mkdep | ||
mkinstalldirs | ||
move-if-change | ||
multilib.am | ||
README | ||
README-maintainer-mode | ||
setup.com | ||
src-release.sh | ||
symlink-tree | ||
test-driver | ||
ylwrap |
README for GNU development tools This directory contains various GNU compilers, assemblers, linkers, debuggers, etc., plus their support routines, definitions, and documentation. If you are receiving this as part of a GDB release, see the file gdb/README. If with a binutils release, see binutils/README; if with a libg++ release, see libg++/README, etc. That'll give you info about this package -- supported targets, how to use it, how to report bugs, etc. It is now possible to automatically configure and build a variety of tools with one command. To build all of the tools contained herein, run the ``configure'' script here, e.g.: ./configure make To install them (by default in /usr/local/bin, /usr/local/lib, etc), then do: make install (If the configure script can't determine your type of computer, give it the name as an argument, for instance ``./configure sun4''. You can use the script ``config.sub'' to test whether a name is recognized; if it is, config.sub translates it to a triplet specifying CPU, vendor, and OS.) If you have more than one compiler on your system, it is often best to explicitly set CC in the environment before running configure, and to also set CC when running make. For example (assuming sh/bash/ksh): CC=gcc ./configure make A similar example using csh: setenv CC gcc ./configure make Much of the code and documentation enclosed is copyright by the Free Software Foundation, Inc. See the file COPYING or COPYING.LIB in the various directories, for a description of the GNU General Public License terms under which you can copy the files. REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info on where and how to report problems.