This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [non-stop] 08/10 linux native support


On Thu, Jul 10, 2008 at 07:01:23PM +0100, Pedro Alves wrote:
> Because we hit this in find_new_threads_callback:
> 
>   if (ti.ti_tid == 0)
>     {
>       /* A thread ID of zero means that this is the main thread, but
> 	 glibc has not yet initialized thread-local storage and the
> 	 pthread library.  We do not know what the thread's TID will
> 	 be yet.  Just enable event reporting and otherwise ignore
> 	 it.  */

Right.  Could you try this version?

Basically the same as your previous posting, except that I moved the
logic assuring we find the first thread when we find the first child
into the thread-db layer.

-- 
Daniel Jacobowitz
CodeSourcery

2008-07-02  Pedro Alves  <pedro@codesourcery.com>

	Non-stop linux native.

	* linux-fork.c (linux_fork_killall): Use SIGKILL instead of
	PTRACE_KILL.

	* linux-nat.c (linux_test_for_tracefork): Block events while we're
	here.
	(find_lwp_pid): Rename to...
	(linux_nat_find_lwp_pid): ... this.  Make public.  Update all
	callers.
	(get_pending_status): Implement non-stop mode.
	(linux_nat_detach): Stop threads before detaching.
	(linux_nat_resume): In non-stop mode, always resume only a single
	PTID.
	(linux_handle_extended_wait): On a clone event, add new lwp to
	GDB's thread table, and mark as running, executing and stopped
	appropriately.
	(linux_nat_filter_event): Don't assume there are other running
	threads when a thread exits.
	(linux_nat_wait): Mark the main thread as running and executing.
	In non-stop mode, don't stop all lwps.
	(linux_nat_kill): Stop lwps before killing them.
	(linux_nat_thread_alive): Use signal 0 to detect if a thread is
	alive.
	(send_sigint_callback): New.
	(linux_nat_stop): New.
	(linux_nat_add_target): Set to_stop to linux_nat_stop.

	* linux-nat.h (thread_db_attach_lwp): Declare.
	(linux_nat_find_lwp_pid): Declare.

	* linux-thread-db.c (check_event): Set proc_handle.pid to the stopped
	lwp.
	(thread_from_lwp, enable_thread_event) Likewise.  Check for new threads
	if we have none.
	(thread_db_attach_lwp): New.
	(thread_db_find_new_threads_1): New, from thread_db_find_new_threads.
	If current lwp is executing, don't try to read from it.
	(thread_db_find_new_threads, thread_db_wait)
	(thread_db_get_thread_local_address): Use thread_db_find_new_threads_1.
	(thread_get_info_callback): Check for new threads if we have none.

--- src/gdb/linux-fork.c	24 Apr 2008 10:21:44 -0000	1.18
+++ src/gdb/linux-fork.c	10 Jul 2008 19:53:11 -0000
@@ -337,7 +337,9 @@ linux_fork_killall (void)
     {
       pid = PIDGET (fp->ptid);
       do {
-	ptrace (PT_KILL, pid, 0, 0);
+	/* Use SIGKILL instead of PTRACE_KILL because the former works even
+	   if the thread is running, while the later doesn't.  */
+	kill (pid, SIGKILL);
 	ret = waitpid (pid, &status, 0);
 	/* We might get a SIGCHLD instead of an exit status.  This is
 	 aggravated by the first kill above - a child has just
--- src/gdb/linux-nat.c	10 Jul 2008 09:30:59 -0000	1.92
+++ src/gdb/linux-nat.c	10 Jul 2008 19:53:11 -0000
@@ -319,6 +319,9 @@ static void linux_nat_async (void (*call
 static int linux_nat_async_mask (int mask);
 static int kill_lwp (int lwpid, int signo);
 
+static int send_sigint_callback (struct lwp_info *lp, void *data);
+static int stop_callback (struct lwp_info *lp, void *data);
+
 /* Captures the result of a successful waitpid call, along with the
    options used in that call.  */
 struct waitpid_result
@@ -521,6 +524,9 @@ linux_test_for_tracefork (int original_p
 {
   int child_pid, ret, status;
   long second_pid;
+  enum sigchld_state async_events_original_state;
+
+  async_events_original_state = linux_nat_async_events (sigchld_sync);
 
   linux_supports_tracefork_flag = 0;
   linux_supports_tracevforkdone_flag = 0;
@@ -551,6 +557,7 @@ linux_test_for_tracefork (int original_p
       if (ret != 0)
 	{
 	  warning (_("linux_test_for_tracefork: failed to kill child"));
+	  linux_nat_async_events (async_events_original_state);
 	  return;
 	}
 
@@ -561,6 +568,7 @@ linux_test_for_tracefork (int original_p
 	warning (_("linux_test_for_tracefork: unexpected wait status 0x%x from "
 		 "killed child"), status);
 
+      linux_nat_async_events (async_events_original_state);
       return;
     }
 
@@ -600,6 +608,8 @@ linux_test_for_tracefork (int original_p
   if (ret != 0)
     warning (_("linux_test_for_tracefork: failed to kill child"));
   my_waitpid (child_pid, &status, 0);
+
+  linux_nat_async_events (async_events_original_state);
 }
 
 /* Return non-zero iff we have tracefork functionality available.
@@ -1019,8 +1029,8 @@ delete_lwp (ptid_t ptid)
 /* Return a pointer to the structure describing the LWP corresponding
    to PID.  If no corresponding LWP could be found, return NULL.  */
 
-static struct lwp_info *
-find_lwp_pid (ptid_t ptid)
+struct lwp_info *
+linux_nat_find_lwp_pid (ptid_t ptid)
 {
   struct lwp_info *lp;
   int lwp;
@@ -1241,7 +1251,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
 
   async_events_original_state = linux_nat_async_events (sigchld_sync);
 
-  lp = find_lwp_pid (ptid);
+  lp = linux_nat_find_lwp_pid (ptid);
 
   /* We assume that we're already attached to any LWP that has an id
      equal to the overall process id, and to any LWP that is already
@@ -1441,16 +1451,80 @@ get_pending_status (struct lwp_info *lp,
      events are always cached in waitpid_queue.  */
 
   *status = 0;
-  if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
+
+  if (non_stop)
     {
-      if (stop_signal != TARGET_SIGNAL_0
-	  && signal_pass_state (stop_signal))
-	*status = W_STOPCODE (target_signal_to_host (stop_signal));
+      enum target_signal signo = TARGET_SIGNAL_0;
+
+      if (is_executing (lp->ptid))
+	{
+	  /* If the core thought this lwp was executing --- e.g., the
+	     executing property hasn't been updated yet, but the
+	     thread has been stopped with a stop_callback /
+	     stop_wait_callback sequence (see linux_nat_detach for
+	     example) --- we can only have pending events in the local
+	     queue.  */
+	  if (queued_waitpid (GET_LWP (lp->ptid), status, __WALL) != -1)
+	    {
+	      if (WIFSTOPPED (status))
+		signo = target_signal_from_host (WSTOPSIG (status));
+
+	      /* If not stopped, then the lwp is gone, no use in
+		 resending a signal.  */
+	    }
+	}
+      else
+	{
+	  /* If the core knows the thread is not executing, then we
+	     have the last signal recorded in
+	     thread_info->stop_signal, unless this is inferior_ptid,
+	     in which case, it's in the global stop_signal, due to
+	     context switching.  */
+
+	  if (ptid_equal (lp->ptid, inferior_ptid))
+	    signo = stop_signal;
+	  else
+	    {
+	      struct thread_info *tp = find_thread_pid (lp->ptid);
+	      gdb_assert (tp);
+	      signo = tp->stop_signal;
+	    }
+	}
+
+      if (signo != TARGET_SIGNAL_0
+	  && !signal_pass_state (signo))
+	{
+	  if (debug_linux_nat)
+	    fprintf_unfiltered (gdb_stdlog, "\
+GPT: lwp %s had signal %s, but it is in no pass state\n",
+				target_pid_to_str (lp->ptid),
+				target_signal_to_string (signo));
+	}
+      else
+	{
+	  if (signo != TARGET_SIGNAL_0)
+	    *status = W_STOPCODE (target_signal_to_host (signo));
+
+	  if (debug_linux_nat)
+	    fprintf_unfiltered (gdb_stdlog,
+				"GPT: lwp %s as pending signal %s\n",
+				target_pid_to_str (lp->ptid),
+				target_signal_to_string (signo));
+	}
     }
-  else if (target_can_async_p ())
-    queued_waitpid (GET_LWP (lp->ptid), status, __WALL);
   else
-    *status = lp->status;
+    {
+      if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
+	{
+	  if (stop_signal != TARGET_SIGNAL_0
+	      && signal_pass_state (stop_signal))
+	    *status = W_STOPCODE (target_signal_to_host (stop_signal));
+	}
+      else if (target_can_async_p ())
+	queued_waitpid (GET_LWP (lp->ptid), status, __WALL);
+      else
+	*status = lp->status;
+    }
 
   return 0;
 }
@@ -1514,6 +1588,13 @@ linux_nat_detach (char *args, int from_t
   if (target_can_async_p ())
     linux_nat_async (NULL, 0);
 
+  /* Stop all threads before detaching.  ptrace requires that the
+     thread is stopped to sucessfully detach.  */
+  iterate_over_lwps (stop_callback, NULL);
+  /* ... and wait until all of them have reported back that
+     they're no longer running.  */
+  iterate_over_lwps (stop_wait_callback, NULL);
+
   iterate_over_lwps (detach_callback, NULL);
 
   /* Only the initial process should be left right now.  */
@@ -1603,19 +1684,27 @@ linux_nat_resume (ptid_t ptid, int step,
   /* A specific PTID means `step only this process id'.  */
   resume_all = (PIDGET (ptid) == -1);
 
-  if (resume_all)
-    iterate_over_lwps (resume_set_callback, NULL);
-  else
-    iterate_over_lwps (resume_clear_callback, NULL);
+  if (non_stop && resume_all)
+    internal_error (__FILE__, __LINE__,
+		    "can't resume all in non-stop mode");
+
+  if (!non_stop)
+    {
+      if (resume_all)
+	iterate_over_lwps (resume_set_callback, NULL);
+      else
+	iterate_over_lwps (resume_clear_callback, NULL);
+    }
 
   /* If PID is -1, it's the current inferior that should be
      handled specially.  */
   if (PIDGET (ptid) == -1)
     ptid = inferior_ptid;
 
-  lp = find_lwp_pid (ptid);
+  lp = linux_nat_find_lwp_pid (ptid);
   gdb_assert (lp != NULL);
 
+  /* Convert to something the lower layer understands.  */
   ptid = pid_to_ptid (GET_LWP (lp->ptid));
 
   /* Remember if we're stepping.  */
@@ -1766,9 +1855,12 @@ linux_handle_extended_wait (struct lwp_i
 	ourstatus->kind = TARGET_WAITKIND_VFORKED;
       else
 	{
+	  struct cleanup *old_chain;
+
 	  ourstatus->kind = TARGET_WAITKIND_IGNORE;
 	  new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (inferior_ptid)));
 	  new_lp->cloned = 1;
+	  new_lp->stopped = 1;
 
 	  if (WSTOPSIG (status) != SIGSTOP)
 	    {
@@ -1785,20 +1877,33 @@ linux_handle_extended_wait (struct lwp_i
 	  else
 	    status = 0;
 
-	  if (stopping)
-	    new_lp->stopped = 1;
-	  else
+	  /* "Attach"ing to the child adds it to GDB's thread list, if
+	     thread_db is active.  */
+	  if (!thread_db_attach_lwp (new_lp->ptid))
+	    {
+	      /* We're not using thread_db.  Attach and add it to
+		 GDB's list.  */
+	      lin_lwp_attach_lwp (new_lp->ptid);
+	      target_post_attach (GET_LWP (new_lp->ptid));
+	      add_thread (new_lp->ptid);
+	    }
+
+	  if (!stopping)
 	    {
+	      new_lp->stopped = 0;
 	      new_lp->resumed = 1;
 	      ptrace (PTRACE_CONT,
 		      PIDGET (lp->waitstatus.value.related_pid), 0,
 		      status ? WSTOPSIG (status) : 0);
+	      set_running (new_lp->ptid, 1);
+	      set_executing (new_lp->ptid, 1);
 	    }
 
 	  if (debug_linux_nat)
 	    fprintf_unfiltered (gdb_stdlog,
 				"LHEW: Got clone event from LWP %ld, resuming\n",
 				GET_LWP (lp->ptid));
+	  lp->stopped = 0;
 	  ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
 
 	  return 1;
@@ -2433,7 +2538,7 @@ linux_nat_filter_event (int lwpid, int s
 {
   struct lwp_info *lp;
 
-  lp = find_lwp_pid (pid_to_ptid (lwpid));
+  lp = linux_nat_find_lwp_pid (pid_to_ptid (lwpid));
 
   /* Check for stop events reported by a process we didn't already
      know about - anything not already in our LWP list.
@@ -2528,13 +2633,7 @@ linux_nat_filter_event (int lwpid, int s
 	 not the end of the debugged application and should be
 	 ignored.  */
       if (num_lwps > 0)
-	{
-	  /* Make sure there is at least one thread running.  */
-	  gdb_assert (iterate_over_lwps (running_callback, NULL));
-
-	  /* Discard the event.  */
-	  return NULL;
-	}
+	return NULL;
     }
 
   /* Check if the current LWP has previously exited.  In the nptl
@@ -2664,6 +2763,8 @@ linux_nat_wait (ptid_t ptid, struct targ
       lp->resumed = 1;
       /* Add the main thread to GDB's thread list.  */
       add_thread_silent (lp->ptid);
+      set_running (lp->ptid, 1);
+      set_executing (lp->ptid, 1);
     }
 
   sigemptyset (&flush_mask);
@@ -2710,7 +2811,7 @@ retry:
 			    target_pid_to_str (ptid));
 
       /* We have a specific LWP to check.  */
-      lp = find_lwp_pid (ptid);
+      lp = linux_nat_find_lwp_pid (ptid);
       gdb_assert (lp);
       status = lp->status;
       lp->status = 0;
@@ -2891,19 +2992,23 @@ retry:
     fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
 			status_to_str (status), target_pid_to_str (lp->ptid));
 
-  /* Now stop all other LWP's ...  */
-  iterate_over_lwps (stop_callback, NULL);
+  if (!non_stop)
+    {
+      /* Now stop all other LWP's ...  */
+      iterate_over_lwps (stop_callback, NULL);
 
-  /* ... and wait until all of them have reported back that they're no
-     longer running.  */
-  iterate_over_lwps (stop_wait_callback, &flush_mask);
-  iterate_over_lwps (flush_callback, &flush_mask);
-
-  /* If we're not waiting for a specific LWP, choose an event LWP from
-     among those that have had events.  Giving equal priority to all
-     LWPs that have had events helps prevent starvation.  */
-  if (pid == -1)
-    select_event_lwp (&lp, &status);
+      /* ... and wait until all of them have reported back that
+	 they're no longer running.  */
+      iterate_over_lwps (stop_wait_callback, &flush_mask);
+      iterate_over_lwps (flush_callback, &flush_mask);
+
+      /* If we're not waiting for a specific LWP, choose an event LWP
+	 from among those that have had events.  Giving equal priority
+	 to all LWPs that have had events helps prevent
+	 starvation.  */
+      if (pid == -1)
+	select_event_lwp (&lp, &status);
+    }
 
   /* Now that we've selected our final event LWP, cancel any
      breakpoints in other LWPs that have hit a GDB breakpoint.  See
@@ -3035,6 +3140,13 @@ linux_nat_kill (void)
     }
   else
     {
+      /* Stop all threads before killing them, since ptrace requires
+	 that the thread is stopped to sucessfully PTRACE_KILL.  */
+      iterate_over_lwps (stop_callback, NULL);
+      /* ... and wait until all of them have reported back that
+	 they're no longer running.  */
+      iterate_over_lwps (stop_wait_callback, NULL);
+
       /* Kill all LWP's ...  */
       iterate_over_lwps (kill_callback, NULL);
 
@@ -3087,22 +3199,22 @@ linux_nat_xfer_partial (struct target_op
 static int
 linux_nat_thread_alive (ptid_t ptid)
 {
+  int err;
+
   gdb_assert (is_lwp (ptid));
 
-  errno = 0;
-  ptrace (PTRACE_PEEKUSER, GET_LWP (ptid), 0, 0);
+  /* Send signal 0 instead of anything ptrace, because ptracing a
+     running thread errors out claiming that the thread doesn't
+     exist.  */
+  err = kill_lwp (GET_LWP (ptid), 0);
+
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
-			"LLTA: PTRACE_PEEKUSER %s, 0, 0 (%s)\n",
+			"LLTA: KILL(SIG0) %s (%s)\n",
 			target_pid_to_str (ptid),
-			errno ? safe_strerror (errno) : "OK");
+			err ? safe_strerror (err) : "OK");
 
-  /* Not every Linux kernel implements PTRACE_PEEKUSER.  But we can
-     handle that case gracefully since ptrace will first do a lookup
-     for the process based upon the passed-in pid.  If that fails we
-     will get either -ESRCH or -EPERM, otherwise the child exists and
-     is alive.  */
-  if (errno == ESRCH || errno == EPERM)
+  if (err != 0)
     return 0;
 
   return 1;
@@ -4304,6 +4416,35 @@ linux_nat_set_async_mode (int on)
   linux_nat_async_enabled = on;
 }
 
+static int
+send_sigint_callback (struct lwp_info *lp, void *data)
+{
+  /* Use is_running instead of !lp->stopped, because the lwp may be
+     stopped due to an internal event, and we want to interrupt it in
+     that case too.  What we want is to check if the thread is stopped
+     from the point of view of the user.  */
+  if (is_running (lp->ptid))
+    kill_lwp (GET_LWP (lp->ptid), SIGINT);
+  return 0;
+}
+
+static void
+linux_nat_stop (ptid_t ptid)
+{
+  if (non_stop)
+    {
+      if (ptid_equal (ptid, minus_one_ptid))
+	iterate_over_lwps (send_sigint_callback, &ptid);
+      else
+	{
+	  struct lwp_info *lp = linux_nat_find_lwp_pid (ptid);
+	  send_sigint_callback (lp, NULL);
+	}
+    }
+  else
+    linux_ops->to_stop (ptid);
+}
+
 void
 linux_nat_add_target (struct target_ops *t)
 {
@@ -4334,6 +4475,9 @@ linux_nat_add_target (struct target_ops 
   t->to_terminal_inferior = linux_nat_terminal_inferior;
   t->to_terminal_ours = linux_nat_terminal_ours;
 
+  /* Methods for non-stop support.  */
+  t->to_stop = linux_nat_stop;
+
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
@@ -4361,7 +4505,7 @@ linux_nat_set_new_thread (struct target_
 struct siginfo *
 linux_nat_get_siginfo (ptid_t ptid)
 {
-  struct lwp_info *lp = find_lwp_pid (ptid);
+  struct lwp_info *lp = linux_nat_find_lwp_pid (ptid);
 
   gdb_assert (lp != NULL);
 
--- src/gdb/linux-nat.h	21 Mar 2008 15:44:53 -0000	1.23
+++ src/gdb/linux-nat.h	10 Jul 2008 19:53:11 -0000
@@ -94,6 +94,8 @@ void check_for_thread_db (void);
 /* Tell the thread_db layer what native target operations to use.  */
 void thread_db_init (struct target_ops *);
 
+int thread_db_attach_lwp (ptid_t ptid);
+
 /* Find process PID's pending signal set from /proc/pid/status.  */
 void linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored);
 
@@ -107,6 +109,8 @@ struct lwp_info *iterate_over_lwps (int 
 						     void *), 
 				    void *data);
 
+struct lwp_info *linux_nat_find_lwp_pid (ptid_t ptid);
+
 /* Create a prototype generic GNU/Linux target.  The client can
    override it with local methods.  */
 struct target_ops * linux_target (void);
--- src/gdb/linux-thread-db.c	5 Jun 2008 21:03:59 -0000	1.44
+++ src/gdb/linux-thread-db.c	10 Jul 2008 19:53:11 -0000
@@ -142,6 +142,7 @@ static CORE_ADDR td_create_bp_addr;
 static CORE_ADDR td_death_bp_addr;
 
 /* Prototypes for local functions.  */
+static void thread_db_find_new_threads_1 (ptid_t ptid);
 static void thread_db_find_new_threads (void);
 static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
 			   const td_thrinfo_t *ti_p);
@@ -283,7 +284,10 @@ thread_get_info_callback (const td_thrha
   if (thread_info == NULL)
     {
       /* New thread.  Attach to it now (why wait?).  */
-      attach_thread (thread_ptid, thp, &ti);
+      if (!have_threads ())
+	thread_db_find_new_threads_1 (thread_ptid);
+      else
+	attach_thread (thread_ptid, thp, &ti);
       thread_info = find_thread_pid (thread_ptid);
       gdb_assert (thread_info != NULL);
     }
@@ -308,6 +312,8 @@ thread_from_lwp (ptid_t ptid)
      LWP.  */
   gdb_assert (GET_LWP (ptid) != 0);
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
   err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
   if (err != TD_OK)
     error (_("Cannot find user-level thread for LWP %ld: %s"),
@@ -332,6 +338,48 @@ thread_from_lwp (ptid_t ptid)
 }
 
 
+/* Attach to lwp PTID, doing whatever else is required to have this
+   LWP under the debugger's control --- e.g., enabling event
+   reporting.  Returns true on success.  */
+int
+thread_db_attach_lwp (ptid_t ptid)
+{
+  td_thrhandle_t th;
+  td_thrinfo_t ti;
+  td_err_e err;
+
+  if (!using_thread_db)
+    return 0;
+
+  /* This ptid comes from linux-nat.c, which should always fill in the
+     LWP.  */
+  gdb_assert (GET_LWP (ptid) != 0);
+
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
+
+  /* If we have only looked at the first thread before libpthread was
+     initialized, we may not know its thread ID yet.  Make sure we do
+     before we add another thread to the list.  */
+  if (!have_threads ())
+    thread_db_find_new_threads_1 (ptid);
+
+  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+  if (err != TD_OK)
+    /* Cannot find user-level thread.  */
+    return 0;
+
+  err = td_thr_get_info_p (&th, &ti);
+  if (err != TD_OK)
+    {
+      warning (_("Cannot get thread info: %s"), thread_db_err_str (err));
+      return 0;
+    }
+
+  attach_thread (ptid, &th, &ti);
+  return 1;
+}
+
 void
 thread_db_init (struct target_ops *target)
 {
@@ -418,6 +466,9 @@ enable_thread_event (td_thragent_t *thre
   td_notify_t notify;
   td_err_e err;
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (inferior_ptid);
+
   /* Get the breakpoint address for thread EVENT.  */
   err = td_ta_event_addr_p (thread_agent, event, &notify);
   if (err != TD_OK)
@@ -761,6 +812,15 @@ check_event (ptid_t ptid)
   if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
     return;
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
+
+  /* If we have only looked at the first thread before libpthread was
+     initialized, we may not know its thread ID yet.  Make sure we do
+     before we add another thread to the list.  */
+  if (!have_threads ())
+    thread_db_find_new_threads_1 (ptid);
+
   /* If we are at a create breakpoint, we do not know what new lwp
      was created and cannot specifically locate the event message for it.
      We have to call td_ta_event_getmsg() to get
@@ -844,7 +904,7 @@ thread_db_wait (ptid_t ptid, struct targ
   /* If we do not know about the main thread yet, this would be a good time to
      find it.  */
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
-    thread_db_find_new_threads ();
+    thread_db_find_new_threads_1 (ptid);
 
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
@@ -951,11 +1011,21 @@ find_new_threads_callback (const td_thrh
   return 0;
 }
 
+/* Search for new threads, accessing memory through stopped thread
+   PTID.  */
+
 static void
-thread_db_find_new_threads (void)
+thread_db_find_new_threads_1 (ptid_t ptid)
 {
   td_err_e err;
+  struct lwp_info *lp = linux_nat_find_lwp_pid (ptid);
 
+  if (!lp || !lp->stopped)
+    /* In linux, we can only read memory through a stopped lwp.  */
+    return;
+
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
   /* Iterate over all user-space threads to discover new threads.  */
   err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
 			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
@@ -964,6 +1034,12 @@ thread_db_find_new_threads (void)
     error (_("Cannot find new threads: %s"), thread_db_err_str (err));
 }
 
+static void
+thread_db_find_new_threads (void)
+{
+  thread_db_find_new_threads_1 (inferior_ptid);
+}
+
 static char *
 thread_db_pid_to_str (ptid_t ptid)
 {
@@ -1015,7 +1091,7 @@ thread_db_get_thread_local_address (ptid
 
   /* If we have not discovered any threads yet, check now.  */
   if (!have_threads ())
-    thread_db_find_new_threads ();
+    thread_db_find_new_threads_1 (ptid);
 
   /* Find the matching thread.  */
   thread_info = find_thread_pid (ptid);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]