Avoid constant stream of TARGET_WAITKIND_NO_RESUMED
authorPedro Alves <pedro@palves.net>
Sat, 4 Jul 2020 18:31:21 +0000 (19:31 +0100)
committerPedro Alves <palves@redhat.com>
Fri, 10 Jul 2020 22:49:34 +0000 (23:49 +0100)
If we hit the synchronous execution command case described by
handle_no_resumed, and handle_no_resumed determines that the event
should be ignored, because it found a thread that is executing, we end
up in prepare_to_wait.

There, if the current target is not registered in the event loop right
now, we call mark_infrun_async_event_handler.  With that event handler
marked, the event loop calls again into fetch_inferior_event, which
calls target_wait, which returns TARGET_WAITKIND_NO_RESUMED, and we
end up in handle_no_resumed, again ignoring the event and marking
infrun_async_event_handler.  The result is that GDB is now always
keeping the CPU 100% busy in this loop, even though it continues to be
able to react to input and to real target events, because we still go
through the event-loop.

The problem is that marking of the infrun_async_event_handler in
prepare_to_wait.  That is there to handle targets that don't support
asynchronous execution.  So the correct predicate is whether async
execution is supported, not whether the target is async right now.

gdb/ChangeLog:

PR gdb/26199
* infrun.c (prepare_to_wait): Check target_can_async_p instead of
target_is_async_p.

gdb/ChangeLog
gdb/infrun.c

index 679f2d25182c776602b9f33b81210c4cefbf8de4..09198ef6ab8f2c56c03c55aaf7aa89da138e1e86 100644 (file)
@@ -1,3 +1,9 @@
+2020-07-10  Pedro Alves  <pedro@palves.net>
+
+       PR gdb/26199
+       * infrun.c (prepare_to_wait): Check target_can_async_p instead of
+       target_is_async_p.
+
 2020-07-10  Pedro Alves  <pedro@palves.net>
 
        PR gdb/26199
index 6b655d4430164268ee3aff92c9b1db2436e2131c..a01e0969cb17943708ecb64f13f165bcea9d7b29 100644 (file)
@@ -8116,7 +8116,11 @@ prepare_to_wait (struct execution_control_state *ecs)
 
   ecs->wait_some_more = 1;
 
-  if (!target_is_async_p ())
+  /* If the target can't async, emulate it by marking the infrun event
+     handler such that as soon as we get back to the event-loop, we
+     immediately end up in fetch_inferior_event again calling
+     target_wait.  */
+  if (!target_can_async_p ())
     mark_infrun_async_event_handler ();
 }