# gdb-7.4.1 thread.c:613 internal-error: is_thread_state: Assertion 'tp' failed



## raghu (May 31, 2012)

OS: FreeBSD 7.4
GDB Version: 7.4.1 (compiled for FreeBSD 7.4)
Arch: amd64

[Note: a bit long email]

Problem:
While debugging a multi-threaded app that creates/deletes a bunch of threads, my GDB session, once every few runs, gets into a state where I cannot debug anymore.

First I get the error message

```
Invalid selected thread
```

At that point, I can look at all the threads using info thread. Now, if I select an available thread and continue, I get the following error

```
thread.c:620: 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)
```

I debugged it a bit further and here is what I found:

fbsd_thread_wait() in fbsd-threads.c function has the following code indicated as a hack


```
if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret))
        {
          delete_thread (inferior_ptid);
          inferior_ptid = ret;
        }
```
Here is the sequence that results in the "Invalid selected thread" message.


The delete_thread() in the above code sets the state of the thread associated with the inferior_ptid as exited (THREAD_EXITED).
wait_for_inferior() function in infrun.c gets called and the call to target_wait() inside that function returns the 'ptid' of the thread that was deleted above.
The handle_inferior_event() function called from wait_for_inferior does a switch_to_thread() to the thread deleted above. Here is the code fragment that does the switch:

```
/* See if something interesting happened to the non-current thread.  If
     so, then switch to that thread.  */
  if (!ptid_equal (ecs->ptid, inferior_ptid))
    {
      if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");

      context_switch (ecs->ptid);

      if (deprecated_context_hook)
        deprecated_context_hook (pid_to_thread_id (ecs->ptid));
    }

  /* At this point, get hold of the now-current thread's frame.  */
  frame = get_current_frame ();
  gdbarch = get_frame_arch (frame)
```

 The call to get_frame_arch() after the switch displays the error "Invalid selected thread" as the thread had exited

After getting into the "Invalid select thread" state, if I select an available thread and continue, 

 prune_threads() gets called and deletes all the threads that exited
 prepare_to_proceed() get called. This function retrieves the last_target_status and ptid, which points to the thread that got deleted by the "hack" in fbsd-threads.c, and tries to switch to that thread using the following code fragment

```
/* Switched over from WAIT_PID.  */
  if (!ptid_equal (wait_ptid, minus_one_ptid)
      && !ptid_equal (inferior_ptid, wait_ptid))
    {
      struct regcache *regcache = get_thread_regcache (wait_ptid);

      if (breakpoint_here_p (get_regcache_aspace (regcache),
                             regcache_read_pc (regcache)))
        {
          /* If stepping, remember current thread to switch back to.  */
          if (step)
            deferred_step_ptid = inferior_ptid;

          /* Switch back to WAIT_PID thread.  */
          switch_to_thread (wait_ptid);

          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
                                "infrun: prepare_to_proceed (step=%d), "
                                "switched to [%s]\n",
                                step, target_pid_to_str (inferior_ptid));

          /* We return 1 to indicate that there is a breakpoint here,
             so we need to step over it before continuing to avoid
             hitting it straight away.  */
          return 1;
        }
    }
```

 switch_to_thread() calls is_exited(), which asserts as it does not find the thread in the thread list


I'm not sure how exactly to fix this issue, as I've seen the "hack" in fbsd_thread_wait() getting called other times without any issue. It only seems to be an issue when the "hack" deletes a thread and a subsequent call to fbsd_thread_wait() returns the ptid of the thread that was deleted.

I can open a bug report if this is an issue, but also looking to see if there is an easy fix that I can use to correct the problem.

Thanks,
-Raghu


----------

