aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2008-10-08 19:16:31 +0000
committerPedro Alves <palves@redhat.com>2008-10-08 19:16:31 +0000
commite24a49d86df6a5cdd58f36c65e25911aa30e52d8 (patch)
tree785e23a92a022df32b8c045ea5480055956d3195 /gdb/remote.c
parent06d61999fb9ffcfa5c7e03315773094e5ee8abab (diff)
downloadgdb-e24a49d86df6a5cdd58f36c65e25911aa30e52d8.zip
gdb-e24a49d86df6a5cdd58f36c65e25911aa30e52d8.tar.gz
gdb-e24a49d86df6a5cdd58f36c65e25911aa30e52d8.tar.bz2
* remote.c (struct remote_state) <waiting_for_stop_reply>: New
field. (remote_open_1): Clear waiting_for_stop_reply. (remote_resume): Set waiting_for_stop_reply. (remote_wait): Clear or set waiting_for_stop_reply accordingly. (putpkt_binary): If we're in async mode and waiting for a stop reply, bail out with an error. (extended_remote_mourn_1): Clear waiting_for_stop_reply.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r--gdb/remote.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index 36dd981..f648c36 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -263,6 +263,14 @@ struct remote_state
/* True if the stub reported support for multi-process
extensions. */
int multi_process_aware;
+
+ /* True if we resumed the target and we're waiting for the target to
+ stop. In the mean time, we can't start another command/query.
+ The remote server wouldn't be ready to process it, so we'd
+ timeout waiting for a reply that would never come and eventually
+ we'd close the connection. This can happen in asynchronous mode
+ because we allow GDB commands while the target is running. */
+ int waiting_for_stop_reply;
};
/* Returns true if the multi-process extensions are in effect. */
@@ -2866,6 +2874,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended
rs->noack_mode = 0;
rs->multi_process_aware = 0;
rs->extended = extended_p;
+ rs->waiting_for_stop_reply = 0;
general_thread = not_sent_ptid;
continue_thread = not_sent_ptid;
@@ -3411,6 +3420,12 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal)
NOT asynchronously. */
if (target_can_async_p ())
target_async (inferior_event_handler, 0);
+
+ /* We've just told the target to resume. The remote server will
+ wait for the inferior to stop, and then send a stop reply. In
+ the mean time, we can't start another command/query ourselves
+ because the stub wouldn't be ready to process it. */
+ rs->waiting_for_stop_reply = 1;
}
@@ -3649,6 +3664,9 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
remote_stopped_by_watchpoint_p = 0;
+ /* We got something. */
+ rs->waiting_for_stop_reply = 0;
+
switch (buf[0])
{
case 'E': /* Error of some sort. */
@@ -3660,6 +3678,10 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
goto got_status;
case 'F': /* File-I/O request. */
remote_fileio_request (buf);
+
+ /* This stop reply is special. We reply back to the stub,
+ and keep waiting for the target to stop. */
+ rs->waiting_for_stop_reply = 1;
continue;
case 'T': /* Status with PC, SP, FP, ... */
{
@@ -3828,6 +3850,10 @@ Packet: '%s'\n"),
}
case 'O': /* Console output. */
remote_console_output (buf + 1);
+
+ /* The target didn't really stop; keep waiting. */
+ rs->waiting_for_stop_reply = 1;
+
if (target_can_async_p ())
{
/* Return immediately to the event loop. The event loop
@@ -3851,11 +3877,17 @@ Packet: '%s'\n"),
strcpy ((char *) buf, last_sent_step ? "s" : "c");
putpkt ((char *) buf);
+
+ /* We just told the target to resume, so a stop reply is
+ in order. */
+ rs->waiting_for_stop_reply = 1;
continue;
}
/* else fallthrough */
default:
warning (_("Invalid remote reply: %s"), buf);
+ /* Keep waiting. */
+ rs->waiting_for_stop_reply = 1;
continue;
}
}
@@ -4968,6 +5000,15 @@ putpkt_binary (char *buf, int cnt)
int tcount = 0;
char *p;
+ /* Catch cases like trying to read memory or listing threads while
+ we're waiting for a stop reply. The remote server wouldn't be
+ ready to handle this request, so we'd hang and timeout. We don't
+ have to worry about this in synchronous mode, because in that
+ case it's not possible to issue a command while the target is
+ running. */
+ if (target_can_async_p () && rs->waiting_for_stop_reply)
+ error (_("Cannot execute this command while the target is running."));
+
/* We're sending out a new packet. Make sure we don't look at a
stale cached response. */
rs->cached_wait_status = 0;
@@ -5480,6 +5521,10 @@ extended_remote_mourn_1 (struct target_ops *target)
{
struct remote_state *rs = get_remote_state ();
+ /* In case we got here due to an error, but we're going to stay
+ connected. */
+ rs->waiting_for_stop_reply = 0;
+
/* Unlike "target remote", we do not want to unpush the target; then
the next time the user says "run", we won't be connected. */