Avoid switch to invalid ptid during Ada task switch.
authorJoel Brobecker <brobecker@gnat.com>
Tue, 16 Mar 2010 18:47:15 +0000 (18:47 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Tue, 16 Mar 2010 18:47:15 +0000 (18:47 +0000)
This is to prevent an internal error during an Ada task switch. A task
switch is simply a thread switch under the hood. What we do is collect
the info from the Ada Task Control Block, deduce the associated thread
ptid, and then switch to that thread.  If the thread ptid computation
routine has not been implemented for the target, of if there is a bug,
then we end up computing a bogus ptid which GDB does not know about,
which eventually leads to an assertion failure:

    (gdb) task 1
    [New Thread 5715]
    /[...]/gdb/thread.c:595: internal-error: is_thread_state:
     Assertion `tp' failed.
    A problem internal to GDB has been detected,
    further debugging may prove unreliable.
    Quit this debugging session? (y or n)

When this happens, it's just nicer for the user to print an error
message, and cancel the task switch. After this patch is applied,
this is what we get:

    (gdb) task 1
    [New Thread 10250]
    Unable to compute thread ID for task 1.
    Cannot switch to this task.

gdb/ChangeLog:

        * ada-tasks.c (task_command_1): Check that the task ptid is valid
        before doing the associated thread switch.

gdb/ChangeLog
gdb/ada-tasks.c

index 0310fccf8c7a51273d04d4f393910c1930f23f3a..f44b0218dedfd2e5c651410eb653f69920c37db3 100644 (file)
@@ -2,6 +2,11 @@
 
        * linux-record.c (record_linux_msghdr): Remove unintended semicolons.
 
+2010-03-16  Joel Brobecker  <brobecker@adacore.com>
+
+       * ada-tasks.c (task_command_1): Check that the task ptid is valid
+       before doing the associated thread switch.
+
 2010-03-16  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * MAINTAINERS: Update my email address.
index be9b8e68a9d62a10614cb3305de2d8cff92cd6f3..519cfc62ba7a8902c6acec67d7ec03dbb12ab264 100644 (file)
@@ -877,6 +877,19 @@ task_command_1 (char *taskno_str, int from_tty)
      to the thread list.  */
   target_find_new_threads ();
 
+  /* Verify that the ptid of the task we want to switch to is valid
+     (in other words, a ptid that GDB knows about).  Otherwise, we will
+     cause an assertion failure later on, when we try to determine
+     the ptid associated thread_info data.  We should normally never
+     encounter such an error, but the wrong ptid can actually easily be
+     computed if target_get_ada_task_ptid has not been implemented for
+     our target (yet).  Rather than cause an assertion error in that case,
+     it's nicer for the user to just refuse to perform the task switch.  */
+  if (!find_thread_ptid (task_info->ptid))
+    error (_("Unable to compute thread ID for task %d.\n"
+             "Cannot switch to this task."),
+           taskno);
+
   switch_to_thread (task_info->ptid);
   ada_find_printable_frame (get_selected_frame (NULL));
   printf_filtered (_("[Switching to task %d]\n"), taskno);