gdb: Mark async event handler when event is already pending
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 23 May 2018 13:25:20 +0000 (14:25 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 12 Jun 2018 20:15:33 +0000 (21:15 +0100)
In PR22882 inferior functions are called on different threads while
scheduler-locking is turned on.  This results in a hang.  This was
discussed in this mailing list thread:

    https://sourceware.org/ml/gdb/2017-10/msg00032.html

The problem is that when the thread is set running in order to execute
the inferior call, a call to target_async is made.  If the target is
not already registered as 'target_async' then this will install the
async event handler, AND unconditionally mark the handler as having an
event pending.

However, if the target is already registered as target_async then the
event handler is not installed (its already installed) and the
handler is NOT marked as having an event pending.

If we try to set running a thread that already has a pending event,
then we do want to set target_async, however, there will not be an
external event incoming (the thread is already stopped) so we rely on
manually marking the event handler as having a pending event in order
to see the threads pending stop event.  This is fine, if, at the point
where we call target_async, the target is not already marked as async.
But, if it is, then the event handler will not be marked as ready, and
the threads pending stop event will never be processed.

A similar pattern of code can be seen in linux_nat_target::resume,
where, when a thread has a pending event, the call to target_async is
followed by a call to async_file_mark to ensure that the pending
thread event will be processed, even if target_async was already set.

gdb/ChangeLog:

PR gdb/22882
* infrun.c (resume_1): Add call to mark_async_event_handler.

gdb/testsuite/ChangeLog:

* gdb.threads/multiple-successive-infcall.exp: Remove kfail case,
rewrite test to describe action performed, rather than possible
failure.

gdb/ChangeLog
gdb/infrun.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.threads/multiple-successive-infcall.exp

index e05561a1e5757f5bdaec22ab02552addb290dd22..692bb5aa33f9ae09a5980318a01905170b3881ac 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-12  Andrew Burgess  <andrew.burgess@embecosm.com>
+           Stephen Roberts  <stephen.roberts@arm.com>
+
+       PR gdb/22882
+       * infrun.c (resume_1): Add call to mark_async_event_handler.
+
 2018-06-12  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * infrun.c (do_target_wait): Change old version of $pc printed.
index 655681ff3601e062d6437db5739886c7e3412496..6f5338c7d0de1b6c56a5c515fd0fce9fe6d2c7b2 100644 (file)
@@ -2408,7 +2408,11 @@ resume_1 (enum gdb_signal sig)
       tp->suspend.stop_signal = GDB_SIGNAL_0;
 
       if (target_can_async_p ())
-       target_async (1);
+       {
+         target_async (1);
+         /* Tell the event loop we have an event to process. */
+         mark_async_event_handler (infrun_async_inferior_event_token);
+       }
       return;
     }
 
index 2324673e56101b43a486a76e7dbfd8af79491b1b..0059828b7be1c3377b721011a7c8859c04228642 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-12  Andrew Burgess  <andrew.burgess@embecosm.com>
+           Stephen Roberts  <stephen.roberts@arm.com>
+
+       * gdb.threads/multiple-successive-infcall.exp: Remove kfail case,
+       rewrite test to describe action performed, rather than possible
+       failure.
+
 2018-06-08  Gary Benson <gbenson@redhat.com>
 
        * gdb.threads/check-libthread-db.exp: New file.
index a71f991d6f26e1118109fc8e267d71fb5a8cb829..bb92c1d487d7e17a4315f5d790977b8ba3b30f55 100644 (file)
@@ -56,17 +56,6 @@ gdb_test "show scheduler-locking" \
 
 foreach_with_prefix thread {5 4 3 2 1}  {
   gdb_test "thread ${thread}" "Switching to .*"
-  set command "call get_value()"
-  set hang_message "testing if ${command} hangs"
-  gdb_test_multiple "${command}" "${hang_message}" {
-    -re "= ${thread}\[\r\n]+${gdb_prompt} $" {
-      pass "${hang_message}"
-    }
-    timeout {
-      kfail "gdb/22882" "${hang_message}"
-      # Exit. The debugger has hung, so there is no point in wasting
-      # time timing out on further calls to get_value().
-      return 0
-    }
-  }
+  gdb_test "call get_value()" "= ${thread}" \
+      "call inferior function"
 }