diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b53cd2b68b..f11092d840 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2021-02-03 Pedro Alves + + * remote.c (remote_notif_stop_ack): Don't error out on + TARGET_WAITKIND_IGNORE; instead, just ignore the notification. + (remote_target::discard_pending_stop_replies): Don't delete + in-flight notification; instead, clear its contents. + 2021-02-03 Pedro Alves * remote.c (extended_remote_target::attach): Set target async in diff --git a/gdb/remote.c b/gdb/remote.c index f183b4f3b0..512bd9467f 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -7006,13 +7006,11 @@ remote_notif_stop_ack (remote_target *remote, /* acknowledge */ putpkt (remote, self->ack_command); - if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE) - { - /* We got an unknown stop reply. */ - error (_("Unknown stop reply")); - } - - remote->push_stop_reply (stop_reply); + /* Kind can be TARGET_WAITKIND_IGNORE if we have meanwhile discarded + the notification. It was left in the queue because we need to + acknowledge it and pull the rest of the notifications out. */ + if (stop_reply->ws.kind != TARGET_WAITKIND_IGNORE) + remote->push_stop_reply (stop_reply); } static int @@ -7181,8 +7179,14 @@ remote_target::discard_pending_stop_replies (struct inferior *inf) /* Discard the in-flight notification. */ if (reply != NULL && reply->ptid.pid () == inf->pid) { - delete reply; - rns->pending_event[notif_client_stop.id] = NULL; + /* Leave the notification pending, since the server expects that + we acknowledge it with vStopped. But clear its contents, so + that later on when we acknowledge it, we also discard it. */ + reply->ws.kind = TARGET_WAITKIND_IGNORE; + + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, + "discarded in-flight notification\n"); } /* Discard the stop replies we have already pulled with diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog index 2f883e05b5..41154d9e19 100644 --- a/gdbserver/ChangeLog +++ b/gdbserver/ChangeLog @@ -1,3 +1,8 @@ +2021-02-03 Pedro Alves + + * server.cc (discard_queued_stop_replies): Don't ever discard the + notification at the head of the list. + 2021-01-20 Simon Marchi * ax.cc (bytecode_address_table): Make static. diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 77e89fe6ed..a5497e93ce 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -203,6 +203,15 @@ discard_queued_stop_replies (ptid_t ptid) next = iter; ++next; + if (iter == notif_stop.queue.begin ()) + { + /* The head of the list contains the notification that was + already sent to GDB. So we can't remove it, otherwise + when GDB sends the vStopped, it would ack the _next_ + notification, which hadn't been sent yet! */ + continue; + } + if (remove_all_on_match_ptid (*iter, ptid)) { delete *iter;