This is the mail archive of the gdb-cvs@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]

[binutils-gdb] Linux native thread create/exit events support


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=aa01bd3689d204ce3d657cf7eb17b8343d79a080

commit aa01bd3689d204ce3d657cf7eb17b8343d79a080
Author: Pedro Alves <palves@redhat.com>
Date:   Tue May 24 14:47:56 2016 +0100

    Linux native thread create/exit events support
    
    A following patch (fix for gdb/19828) makes linux-nat.c add threads to
    GDB's thread list earlier in the "attach" sequence, and that causes a
    surprising regression on
    gdb.threads/attach-many-short-lived-threads.exp on my machine.  The
    extra "thread x exited" handling and traffic slows down that test
    enough that GDB core has trouble keeping up with new threads that are
    spawned while trying to stop existing ones.
    
    I saw the exact same issue with remote/gdbserver a while ago and fixed
    it in 65706a29bac5 (Remote thread create/exit events) so part of the
    fix here is the exact same -- add support for thread created events to
    gdb/linux-nat.c.  infrun.c:stop_all_threads enables those events when
    it tries to stop threads, which ensures that new threads never get a
    chance to themselves start new threads, thus fixing the race.
    
    gdb/
    2016-05-24  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/19828
    	* linux-nat.c (report_thread_events): New global.
    	(linux_handle_extended_wait): Report
    	TARGET_WAITKIND_THREAD_CREATED if thread event reporting is
    	enabled.
    	(wait_lwp, linux_nat_filter_event): Report all thread exits if
    	thread event reporting is enabled.  Remove comment.
    	(filter_exit_event): New function.
    	(linux_nat_wait_1): Use it.
    	(linux_nat_thread_events): New function.
    	(linux_nat_add_target): Install it as target_thread_events method.

Diff:
---
 gdb/ChangeLog         | 14 ++++++++++++
 gdb/linux-nat.c       | 62 ++++++++++++++++++++++++++++++++++++++++++---------
 gdb/linux-thread-db.c | 14 +++++++-----
 3 files changed, 73 insertions(+), 17 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 46f5b42..5b79c48 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2016-05-24  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/19828
+	* linux-nat.c (report_thread_events): New global.
+	(linux_handle_extended_wait): Report
+	TARGET_WAITKIND_THREAD_CREATED if thread event reporting is
+	enabled.
+	(wait_lwp, linux_nat_filter_event): Report all thread exits if
+	thread event reporting is enabled.  Remove comment.
+	(filter_exit_event): New function.
+	(linux_nat_wait_1): Use it.
+	(linux_nat_thread_events): New function.
+	(linux_nat_add_target): Install it as target_thread_events method.
+
 2016-05-24  Yan-Ting Lin  <currygt52@gmail.com>
 
 	* MAINTAINERS (Write After Approval): Add "Yan-Ting Lin".
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index edde88d..19fe12f 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -239,6 +239,9 @@ struct simple_pid_list
 };
 struct simple_pid_list *stopped_pids;
 
+/* Whether target_thread_events is in effect.  */
+static int report_thread_events;
+
 /* Async mode support.  */
 
 /* The read/write ends of the pipe registered as waitable file in the
@@ -1952,6 +1955,11 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
 				    status_to_str (status));
 	      new_lp->status = status;
 	    }
+	  else if (report_thread_events)
+	    {
+	      new_lp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
+	      new_lp->status = status;
+	    }
 
 	  return 1;
 	}
@@ -2091,13 +2099,14 @@ wait_lwp (struct lwp_info *lp)
       /* Check if the thread has exited.  */
       if (WIFEXITED (status) || WIFSIGNALED (status))
 	{
-	  if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+	  if (report_thread_events
+	      || ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
 	    {
 	      if (debug_linux_nat)
-		fprintf_unfiltered (gdb_stdlog, "WL: Process %d exited.\n",
+		fprintf_unfiltered (gdb_stdlog, "WL: LWP %d exited.\n",
 				    ptid_get_pid (lp->ptid));
 
-	      /* This is the leader exiting, it means the whole
+	      /* If this is the leader exiting, it means the whole
 		 process is gone.  Store the status to report to the
 		 core.  Store it in lp->waitstatus, because lp->status
 		 would be ambiguous (W_EXITCODE(0,0) == 0).  */
@@ -2902,7 +2911,8 @@ linux_nat_filter_event (int lwpid, int status)
   /* Check if the thread has exited.  */
   if (WIFEXITED (status) || WIFSIGNALED (status))
     {
-      if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
+      if (!report_thread_events
+	  && num_lwps (ptid_get_pid (lp->ptid)) > 1)
 	{
 	  if (debug_linux_nat)
 	    fprintf_unfiltered (gdb_stdlog,
@@ -2922,15 +2932,9 @@ linux_nat_filter_event (int lwpid, int status)
 	 resumed.  */
       if (debug_linux_nat)
 	fprintf_unfiltered (gdb_stdlog,
-			    "Process %ld exited (resumed=%d)\n",
+			    "LWP %ld exited (resumed=%d)\n",
 			    ptid_get_lwp (lp->ptid), lp->resumed);
 
-      /* This was the last lwp in the process.  Since events are
-	 serialized to GDB core, we may not be able report this one
-	 right now, but GDB core and the other target layers will want
-	 to be notified about the exit code/signal, leave the status
-	 pending for the next time we're able to report it.  */
-
       /* Dead LWP's aren't expected to reported a pending sigstop.  */
       lp->signalled = 0;
 
@@ -3110,6 +3114,30 @@ check_zombie_leaders (void)
     }
 }
 
+/* Convenience function that is called when the kernel reports an exit
+   event.  This decides whether to report the event to GDB as a
+   process exit event, a thread exit event, or to suppress the
+   event.  */
+
+static ptid_t
+filter_exit_event (struct lwp_info *event_child,
+		   struct target_waitstatus *ourstatus)
+{
+  ptid_t ptid = event_child->ptid;
+
+  if (num_lwps (ptid_get_pid (ptid)) > 1)
+    {
+      if (report_thread_events)
+	ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
+      else
+	ourstatus->kind = TARGET_WAITKIND_IGNORE;
+
+      exit_lwp (event_child);
+    }
+
+  return ptid;
+}
+
 static ptid_t
 linux_nat_wait_1 (struct target_ops *ops,
 		  ptid_t ptid, struct target_waitstatus *ourstatus,
@@ -3339,6 +3367,9 @@ linux_nat_wait_1 (struct target_ops *ops,
   else
     lp->core = linux_common_core_of_thread (lp->ptid);
 
+  if (ourstatus->kind == TARGET_WAITKIND_EXITED)
+    return filter_exit_event (lp, ourstatus);
+
   return lp->ptid;
 }
 
@@ -4614,6 +4645,14 @@ linux_nat_fileio_unlink (struct target_ops *self,
   return ret;
 }
 
+/* Implementation of the to_thread_events method.  */
+
+static void
+linux_nat_thread_events (struct target_ops *ops, int enable)
+{
+  report_thread_events = enable;
+}
+
 void
 linux_nat_add_target (struct target_ops *t)
 {
@@ -4646,6 +4685,7 @@ linux_nat_add_target (struct target_ops *t)
   t->to_supports_stopped_by_sw_breakpoint = linux_nat_supports_stopped_by_sw_breakpoint;
   t->to_stopped_by_hw_breakpoint = linux_nat_stopped_by_hw_breakpoint;
   t->to_supports_stopped_by_hw_breakpoint = linux_nat_supports_stopped_by_hw_breakpoint;
+  t->to_thread_events = linux_nat_thread_events;
 
   t->to_can_async_p = linux_nat_can_async_p;
   t->to_is_async_p = linux_nat_is_async_p;
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 284e331..2300c81 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1116,12 +1116,14 @@ thread_db_wait (struct target_ops *ops,
 
   ptid = beneath->to_wait (beneath, ptid, ourstatus, options);
 
-  if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
-    return ptid;
-
-  if (ourstatus->kind == TARGET_WAITKIND_EXITED
-      || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
-    return ptid;
+  switch (ourstatus->kind)
+    {
+    case TARGET_WAITKIND_IGNORE:
+    case TARGET_WAITKIND_EXITED:
+    case TARGET_WAITKIND_THREAD_EXITED:
+    case TARGET_WAITKIND_SIGNALLED:
+      return ptid;
+    }
 
   info = get_thread_db_info (ptid_get_pid (ptid));


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