Blame SOURCES/gdb-rhbz1184724-gdb-internal-error-num-lwps.patch

2c2fa1
From 6681535d2cecea1f67255c140f11b217518a2f4e Mon Sep 17 00:00:00 2001
2c2fa1
From: Pedro Alves <palves@redhat.com>
2c2fa1
Date: Wed, 17 Jun 2015 20:41:05 +0100
2c2fa1
Subject: [PATCH] Fix BZ1184724 - gdb output a internal-error: Assertion
2c2fa1
 `num_lwps (GET_PID (inferior_ptid)) == 1'
2c2fa1
2c2fa1
The real issue with this bug is in the ptrace error:
2c2fa1
2c2fa1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2c2fa1
  (gdb) c
2c2fa1
  Continuing.
2c2fa1
  netcfStateCleanup () at interface/interface_backend_netcf.c:116
2c2fa1
  116	}
2c2fa1
  ptrace: No such process.
2c2fa1
  ^^^^^^^^^^^^^^^^^^^^^^^^
2c2fa1
  (gdb) quit
2c2fa1
	  Inferior 1 [process 11205] will be detached.
2c2fa1
  Quit anyway? (y or n) y
2c2fa1
  [Thread 0x7fefdf322880 (LWP 11205) exited]
2c2fa1
2c2fa1
  ../../gdb/linux-nat.c:1869: internal-error: linux_nat_detach: Assertion `num_lwps (GET_PID (inferior_ptid)) == 1' failed.
2c2fa1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2c2fa1
2c2fa1
The assertion is just a consequence.
2c2fa1
2c2fa1
So the main fix is to backport the GDB [1] bits of upstream 23f238d3
2c2fa1
(Fix race exposed by gdb.threads/killed.exp).  That makes
2c2fa1
linux_resume_one_lwp detect when the LWP being resumed disappears.
2c2fa1
However, we need to backport also part of 8a99810d (linux-nat.c: clean
2c2fa1
up pending status checking and resuming LWPs), which is what
2c2fa1
introduced the centralized linux_resume_one_lwp in the first place,
2c2fa1
and also one bit from 8817a6f2 (PR gdb/15713 - errors from
2c2fa1
i386_linux_resume lead to lock-up), which makes linux_nat_resume not
2c2fa1
clear the leader LWP's lwp->stopped flag too early, otherwise we'd hit
2c2fa1
the new assertion in check_ptrace_stopped_lwp_gone.
2c2fa1
2c2fa1
The test is new (not a backport), and without the fix triggers the
2c2fa1
"detach" assertion shown above.
2c2fa1
2c2fa1
[1] - The equivalent GDBserver bits are harder to backport, as they
2c2fa1
rely on GDB exceptions, which GDBserver 7.6.1 doesn't support yet.
2c2fa1
Fortunately, GDBserver already handles ESRCH from within its
2c2fa1
linux_resume_one_lwp, so doesn't trigger this particular bug and
2c2fa1
passes the test.
2c2fa1
2c2fa1
gdb/ChangeLog:
2c2fa1
2015-06-17  Pedro Alves  <palves@redhat.com>
2c2fa1
2c2fa1
	* common/linux-procfs.c (linux_proc_pid_is_trace_stopped): New
2c2fa1
	function.
2c2fa1
	* common/linux-procfs.h (linux_proc_pid_is_trace_stopped): New
2c2fa1
	declaration.
2c2fa1
	* linux-nat.c (linux_resume_one_lwp_throw, check_ptrace_stopped_lwp_gone)
2c2fa1
	(linux_resume_one_lwp): New functions.
2c2fa1
	(resume_lwp): Use linux_resume_one_lwp.
2c2fa1
	(linux_nat_resume_callback): Skip if LWP is the same as the passed
2c2fa1
	in data pointer.
2c2fa1
	(linux_nat_resume): Don't clear the selected LWP's stopped flag
2c2fa1
	before resuming the sibling LWPs.  Instead pass LWP to
2c2fa1
	linux_nat_resume_callback.  Use linux_resume_one_lwp.
2c2fa1
	(linux_handle_extended_wait, linux_nat_filter_event)
2c2fa1
	(linux_nat_wait_1): Use linux_resume_one_lwp.
2c2fa1
	(resume_stopped_resumed_lwps): Try register reads in TRY/CATCH and
2c2fa1
	swallows errors if the LWP is gone.  Use
2c2fa1
	linux_resume_one_lwp_throw instead of linux_resume_one_lwp.
2c2fa1
2c2fa1
gdb/testsuite/ChangeLog:
2c2fa1
2015-06-17  Pedro Alves  <palves@redhat.com>
2c2fa1
2c2fa1
	* gdb.threads/thread-kills-process.c: New file.
2c2fa1
	* gdb.threads/thread-kills-process.exp: New file.
2c2fa1
---
2c2fa1
 gdb/ChangeLog                                      |  13 ++
2c2fa1
 gdb/common/linux-procfs.c                          |   6 +
2c2fa1
 gdb/common/linux-procfs.h                          |   2 +
2c2fa1
 gdb/linux-nat.c                                    | 200 +++++++++++++--------
2c2fa1
 gdb/testsuite/gdb.threads/thread-kills-process.c   |  62 +++++++
2c2fa1
 gdb/testsuite/gdb.threads/thread-kills-process.exp |  70 ++++++++
2c2fa1
 6 files changed, 277 insertions(+), 76 deletions(-)
2c2fa1
 create mode 100644 gdb/testsuite/gdb.threads/thread-kills-process.c
2c2fa1
 create mode 100644 gdb/testsuite/gdb.threads/thread-kills-process.exp
2c2fa1
2c2fa1
Index: gdb-7.6.1/gdb/common/linux-procfs.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/common/linux-procfs.c
2c2fa1
+++ gdb-7.6.1/gdb/common/linux-procfs.c
2c2fa1
@@ -111,6 +111,12 @@ linux_proc_pid_is_stopped (pid_t pid)
2c2fa1
   return linux_proc_pid_has_state (pid, "T (stopped)");
2c2fa1
 }
2c2fa1
 
2c2fa1
+int
2c2fa1
+linux_proc_pid_is_trace_stopped (pid_t pid)
2c2fa1
+{
2c2fa1
+  return linux_proc_pid_has_state (pid, "T (tracing stop)");
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* See linux-procfs.h declaration.  */
2c2fa1
 
2c2fa1
 int
2c2fa1
Index: gdb-7.6.1/gdb/common/linux-procfs.h
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/common/linux-procfs.h
2c2fa1
+++ gdb-7.6.1/gdb/common/linux-procfs.h
2c2fa1
@@ -36,6 +36,8 @@ extern pid_t linux_proc_get_tracerpid (p
2c2fa1
 
2c2fa1
 extern int linux_proc_pid_is_stopped (pid_t pid);
2c2fa1
 
2c2fa1
+extern int linux_proc_pid_is_trace_stopped (pid_t pid);
2c2fa1
+
2c2fa1
 /* Return non-zero if PID is a zombie.  */
2c2fa1
 
2c2fa1
 extern int linux_proc_pid_is_zombie (pid_t pid);
2c2fa1
Index: gdb-7.6.1/gdb/linux-nat.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/linux-nat.c
2c2fa1
+++ gdb-7.6.1/gdb/linux-nat.c
2c2fa1
@@ -1928,6 +1928,85 @@ linux_nat_detach (struct target_ops *ops
2c2fa1
     linux_ops->to_detach (ops, args, from_tty);
2c2fa1
 }
2c2fa1
 
2c2fa1
+/* Resume execution of the inferior process.  If STEP is nonzero,
2c2fa1
+   single-step it.  If SIGNAL is nonzero, give it that signal.  */
2c2fa1
+
2c2fa1
+static void
2c2fa1
+linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
2c2fa1
+			    enum gdb_signal signo)
2c2fa1
+{
2c2fa1
+  ptid_t ptid;
2c2fa1
+
2c2fa1
+  lp->step = step;
2c2fa1
+
2c2fa1
+  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
+    linux_nat_prepare_to_resume (lp);
2c2fa1
+
2c2fa1
+  ptid = pid_to_ptid (GET_LWP (lp->ptid));
2c2fa1
+  linux_ops->to_resume (linux_ops, ptid, step, signo);
2c2fa1
+
2c2fa1
+  /* Successfully resumed.  Clear state that no longer makes sense,
2c2fa1
+     and mark the LWP as running.  Must not do this before resuming
2c2fa1
+     otherwise if that fails other code will be confused.  E.g., we'd
2c2fa1
+     later try to stop the LWP and hang forever waiting for a stop
2c2fa1
+     status.  Note that we must not throw after this is cleared,
2c2fa1
+     otherwise handle_zombie_lwp_error would get confused.  */
2c2fa1
+  lp->stopped = 0;
2c2fa1
+  lp->stopped_by_watchpoint = 0;
2c2fa1
+  registers_changed_ptid (lp->ptid);
2c2fa1
+}
2c2fa1
+
2c2fa1
+/* Called when we try to resume a stopped LWP and that errors out.  If
2c2fa1
+   the LWP is no longer in ptrace-stopped state (meaning it's zombie,
2c2fa1
+   or about to become), discard the error, clear any pending status
2c2fa1
+   the LWP may have, and return true (we'll collect the exit status
2c2fa1
+   soon enough).  Otherwise, return false.  */
2c2fa1
+
2c2fa1
+static int
2c2fa1
+check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
2c2fa1
+{
2c2fa1
+  /* If we get an error after resuming the LWP successfully, we'd
2c2fa1
+     confuse !T state for the LWP being gone.  */
2c2fa1
+  gdb_assert (lp->stopped);
2c2fa1
+
2c2fa1
+  /* We can't just check whether the LWP is in 'Z (Zombie)' state,
2c2fa1
+     because even if ptrace failed with ESRCH, the tracee may be "not
2c2fa1
+     yet fully dead", but already refusing ptrace requests.  In that
2c2fa1
+     case the tracee has 'R (Running)' state for a little bit
2c2fa1
+     (observed in Linux 3.18).  See also the note on ESRCH in the
2c2fa1
+     ptrace(2) man page.  Instead, check whether the LWP has any state
2c2fa1
+     other than ptrace-stopped.  */
2c2fa1
+
2c2fa1
+  /* Don't assume anything if /proc/PID/status can't be read.  */
2c2fa1
+  if (linux_proc_pid_is_trace_stopped (ptid_get_lwp (lp->ptid)) == 0)
2c2fa1
+    {
2c2fa1
+      lp->status = 0;
2c2fa1
+      lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
2c2fa1
+      lp->stopped_by_watchpoint = 0;
2c2fa1
+      return 1;
2c2fa1
+    }
2c2fa1
+  return 0;
2c2fa1
+}
2c2fa1
+
2c2fa1
+/* Like linux_resume_one_lwp_throw, but no error is thrown if the LWP
2c2fa1
+   disappears while we try to resume it.  */
2c2fa1
+
2c2fa1
+static void
2c2fa1
+linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
2c2fa1
+{
2c2fa1
+  volatile struct gdb_exception ex;
2c2fa1
+
2c2fa1
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
2c2fa1
+    {
2c2fa1
+      linux_resume_one_lwp_throw (lp, step, signo);
2c2fa1
+    }
2c2fa1
+  if (ex.reason < 0)
2c2fa1
+    {
2c2fa1
+      if (!check_ptrace_stopped_lwp_gone (lp))
2c2fa1
+	throw_exception (ex);
2c2fa1
+    }
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* Resume LP.  */
2c2fa1
 
2c2fa1
 static void
2c2fa1
@@ -1956,14 +2035,7 @@ resume_lwp (struct lwp_info *lp, int ste
2c2fa1
 				 : "0"),
2c2fa1
 				step ? "step" : "resume");
2c2fa1
 
2c2fa1
-	  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	    linux_nat_prepare_to_resume (lp);
2c2fa1
-	  linux_ops->to_resume (linux_ops,
2c2fa1
-				pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-				step, signo);
2c2fa1
-	  lp->stopped = 0;
2c2fa1
-	  lp->step = step;
2c2fa1
-	  lp->stopped_by_watchpoint = 0;
2c2fa1
+	  linux_resume_one_lwp (lp, step, signo);
2c2fa1
 	}
2c2fa1
       else
2c2fa1
 	{
2c2fa1
@@ -1982,13 +2054,17 @@ resume_lwp (struct lwp_info *lp, int ste
2c2fa1
     }
2c2fa1
 }
2c2fa1
 
2c2fa1
-/* Resume LWP, with the last stop signal, if it is in pass state.  */
2c2fa1
+/* Callback for iterate_over_lwps.  If LWP is EXCEPT, do nothing.
2c2fa1
+   Resume LWP with the last stop signal, if it is in pass state.  */
2c2fa1
 
2c2fa1
 static int
2c2fa1
-linux_nat_resume_callback (struct lwp_info *lp, void *data)
2c2fa1
+linux_nat_resume_callback (struct lwp_info *lp, void *except)
2c2fa1
 {
2c2fa1
   enum gdb_signal signo = GDB_SIGNAL_0;
2c2fa1
 
2c2fa1
+  if (lp == except)
2c2fa1
+    return 0;
2c2fa1
+
2c2fa1
   if (lp->stopped)
2c2fa1
     {
2c2fa1
       struct thread_info *thread;
2c2fa1
@@ -2108,20 +2184,10 @@ linux_nat_resume (struct target_ops *ops
2c2fa1
       return;
2c2fa1
     }
2c2fa1
 
2c2fa1
-  /* Mark LWP as not stopped to prevent it from being continued by
2c2fa1
-     linux_nat_resume_callback.  */
2c2fa1
-  lp->stopped = 0;
2c2fa1
-
2c2fa1
   if (resume_many)
2c2fa1
-    iterate_over_lwps (ptid, linux_nat_resume_callback, NULL);
2c2fa1
+    iterate_over_lwps (ptid, linux_nat_resume_callback, lp);
2c2fa1
 
2c2fa1
-  /* Convert to something the lower layer understands.  */
2c2fa1
-  ptid = pid_to_ptid (GET_LWP (lp->ptid));
2c2fa1
-
2c2fa1
-  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-    linux_nat_prepare_to_resume (lp);
2c2fa1
-  linux_ops->to_resume (linux_ops, ptid, step, signo);
2c2fa1
-  lp->stopped_by_watchpoint = 0;
2c2fa1
+  linux_resume_one_lwp (lp, step, signo);
2c2fa1
 
2c2fa1
   if (debug_linux_nat)
2c2fa1
     fprintf_unfiltered (gdb_stdlog,
2c2fa1
@@ -2287,11 +2353,7 @@ linux_handle_syscall_trap (struct lwp_in
2c2fa1
 
2c2fa1
   /* Note that gdbarch_get_syscall_number may access registers, hence
2c2fa1
      fill a regcache.  */
2c2fa1
-  registers_changed ();
2c2fa1
-  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-    linux_nat_prepare_to_resume (lp);
2c2fa1
-  linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-			lp->step, GDB_SIGNAL_0);
2c2fa1
+  linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
2c2fa1
   return 1;
2c2fa1
 }
2c2fa1
 
2c2fa1
@@ -2486,22 +2548,15 @@ linux_handle_extended_wait (struct lwp_i
2c2fa1
 		    fprintf_unfiltered (gdb_stdlog,
2c2fa1
 					"LHEW: resuming new LWP %ld\n",
2c2fa1
 					GET_LWP (new_lp->ptid));
2c2fa1
-		  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-		    linux_nat_prepare_to_resume (new_lp);
2c2fa1
-		  linux_ops->to_resume (linux_ops, pid_to_ptid (new_pid),
2c2fa1
-					0, GDB_SIGNAL_0);
2c2fa1
-		  new_lp->stopped = 0;
2c2fa1
+
2c2fa1
+		  linux_resume_one_lwp (new_lp, 0, GDB_SIGNAL_0);
2c2fa1
 		}
2c2fa1
 	    }
2c2fa1
 
2c2fa1
 	  if (debug_linux_nat)
2c2fa1
 	    fprintf_unfiltered (gdb_stdlog,
2c2fa1
 				"LHEW: resuming parent LWP %d\n", pid);
2c2fa1
-	  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	    linux_nat_prepare_to_resume (lp);
2c2fa1
-	  linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-				0, GDB_SIGNAL_0);
2c2fa1
-
2c2fa1
+	  linux_resume_one_lwp (lp, 0, GDB_SIGNAL_0);
2c2fa1
 	  return 1;
2c2fa1
 	}
2c2fa1
 
2c2fa1
@@ -3382,12 +3437,7 @@ linux_nat_filter_event (int lwpid, int s
2c2fa1
 	{
2c2fa1
 	  /* This is a delayed SIGSTOP.  */
2c2fa1
 
2c2fa1
-	  registers_changed ();
2c2fa1
-
2c2fa1
-	  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	    linux_nat_prepare_to_resume (lp);
2c2fa1
-	  linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-			    lp->step, GDB_SIGNAL_0);
2c2fa1
+	  linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
2c2fa1
 	  if (debug_linux_nat)
2c2fa1
 	    fprintf_unfiltered (gdb_stdlog,
2c2fa1
 				"LLW: %s %s, 0, 0 (discard SIGSTOP)\n",
2c2fa1
@@ -3395,7 +3445,6 @@ linux_nat_filter_event (int lwpid, int s
2c2fa1
 				"PTRACE_SINGLESTEP" : "PTRACE_CONT",
2c2fa1
 				target_pid_to_str (lp->ptid));
2c2fa1
 
2c2fa1
-	  lp->stopped = 0;
2c2fa1
 	  gdb_assert (lp->resumed);
2c2fa1
 
2c2fa1
 	  /* Discard the event.  */
2c2fa1
@@ -3416,11 +3465,7 @@ linux_nat_filter_event (int lwpid, int s
2c2fa1
       /* This is a delayed SIGINT.  */
2c2fa1
       lp->ignore_sigint = 0;
2c2fa1
 
2c2fa1
-      registers_changed ();
2c2fa1
-      if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	linux_nat_prepare_to_resume (lp);
2c2fa1
-      linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-			    lp->step, GDB_SIGNAL_0);
2c2fa1
+      linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
2c2fa1
       if (debug_linux_nat)
2c2fa1
 	fprintf_unfiltered (gdb_stdlog,
2c2fa1
 			    "LLW: %s %s, 0, 0 (discard SIGINT)\n",
2c2fa1
@@ -3428,7 +3473,6 @@ linux_nat_filter_event (int lwpid, int s
2c2fa1
 			    "PTRACE_SINGLESTEP" : "PTRACE_CONT",
2c2fa1
 			    target_pid_to_str (lp->ptid));
2c2fa1
 
2c2fa1
-      lp->stopped = 0;
2c2fa1
       gdb_assert (lp->resumed);
2c2fa1
 
2c2fa1
       /* Discard the event.  */
2c2fa1
@@ -3796,11 +3840,7 @@ retry:
2c2fa1
 	     other threads to run.  On the other hand, not resuming
2c2fa1
 	     newly attached threads may cause an unwanted delay in
2c2fa1
 	     getting them running.  */
2c2fa1
-	  registers_changed ();
2c2fa1
-	  if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	    linux_nat_prepare_to_resume (lp);
2c2fa1
-	  linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-				lp->step, signo);
2c2fa1
+	  linux_resume_one_lwp (lp, lp->step, signo);
2c2fa1
 	  if (debug_linux_nat)
2c2fa1
 	    fprintf_unfiltered (gdb_stdlog,
2c2fa1
 				"LLW: %s %s, %s (preempt 'handle')\n",
2c2fa1
@@ -3810,7 +3850,6 @@ retry:
2c2fa1
 				(signo != GDB_SIGNAL_0
2c2fa1
 				 ? strsignal (gdb_signal_to_host (signo))
2c2fa1
 				 : "0"));
2c2fa1
-	  lp->stopped = 0;
2c2fa1
 	  goto retry;
2c2fa1
 	}
2c2fa1
 
2c2fa1
@@ -3935,32 +3974,41 @@ resume_stopped_resumed_lwps (struct lwp_
2c2fa1
     {
2c2fa1
       struct regcache *regcache = get_thread_regcache (lp->ptid);
2c2fa1
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
2c2fa1
-      CORE_ADDR pc = regcache_read_pc (regcache);
2c2fa1
+      volatile struct gdb_exception ex;
2c2fa1
 
2c2fa1
       gdb_assert (is_executing (lp->ptid));
2c2fa1
 
2c2fa1
-      /* Don't bother if there's a breakpoint at PC that we'd hit
2c2fa1
-	 immediately, and we're not waiting for this LWP.  */
2c2fa1
-      if (!ptid_match (lp->ptid, *wait_ptid_p))
2c2fa1
+      TRY_CATCH (ex, RETURN_MASK_ERROR)
2c2fa1
 	{
2c2fa1
-	  if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
2c2fa1
-	    return 0;
2c2fa1
-	}
2c2fa1
+	  CORE_ADDR pc = regcache_read_pc (regcache);
2c2fa1
+	  int leave_stopped = 0;
2c2fa1
 
2c2fa1
-      if (debug_linux_nat)
2c2fa1
-	fprintf_unfiltered (gdb_stdlog,
2c2fa1
-			    "RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n",
2c2fa1
-			    target_pid_to_str (lp->ptid),
2c2fa1
-			    paddress (gdbarch, pc),
2c2fa1
-			    lp->step);
2c2fa1
+	  /* Don't bother if there's a breakpoint at PC that we'd hit
2c2fa1
+	     immediately, and we're not waiting for this LWP.  */
2c2fa1
+	  if (!ptid_match (lp->ptid, *wait_ptid_p))
2c2fa1
+	    {
2c2fa1
+	      if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
2c2fa1
+		leave_stopped = 1;
2c2fa1
+	    }
2c2fa1
 
2c2fa1
-      registers_changed ();
2c2fa1
-      if (linux_nat_prepare_to_resume != NULL)
2c2fa1
-	linux_nat_prepare_to_resume (lp);
2c2fa1
-      linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
2c2fa1
-			    lp->step, GDB_SIGNAL_0);
2c2fa1
-      lp->stopped = 0;
2c2fa1
-      lp->stopped_by_watchpoint = 0;
2c2fa1
+	  if (!leave_stopped)
2c2fa1
+	    {
2c2fa1
+	      if (debug_linux_nat)
2c2fa1
+		fprintf_unfiltered (gdb_stdlog,
2c2fa1
+				    "RSRL: resuming stopped-resumed LWP %s at "
2c2fa1
+				    "%s: step=%d\n",
2c2fa1
+				    target_pid_to_str (lp->ptid),
2c2fa1
+				    paddress (gdbarch, pc),
2c2fa1
+				    lp->step);
2c2fa1
+
2c2fa1
+	      linux_resume_one_lwp_throw (lp, lp->step, GDB_SIGNAL_0);
2c2fa1
+	    }
2c2fa1
+	}
2c2fa1
+      if (ex.reason < 0)
2c2fa1
+	{
2c2fa1
+	  if (!check_ptrace_stopped_lwp_gone (lp))
2c2fa1
+	    throw_exception (ex);
2c2fa1
+	}
2c2fa1
     }
2c2fa1
 
2c2fa1
   return 0;
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.threads/thread-kills-process.c
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.threads/thread-kills-process.c
2c2fa1
@@ -0,0 +1,62 @@
2c2fa1
+/* Copyright 2015 Free Software Foundation, Inc.
2c2fa1
+
2c2fa1
+   This file is part of GDB.
2c2fa1
+
2c2fa1
+   This program is free software; you can redistribute it and/or modify
2c2fa1
+   it under the terms of the GNU General Public License as published by
2c2fa1
+   the Free Software Foundation; either version 3 of the License, or
2c2fa1
+   (at your option) any later version.
2c2fa1
+
2c2fa1
+   This program is distributed in the hope that it will be useful,
2c2fa1
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+   GNU General Public License for more details.
2c2fa1
+
2c2fa1
+   You should have received a copy of the GNU General Public License
2c2fa1
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
2c2fa1
+
2c2fa1
+#include <pthread.h>
2c2fa1
+#include <unistd.h>
2c2fa1
+
2c2fa1
+volatile int call_exit;
2c2fa1
+static pthread_barrier_t barrier;
2c2fa1
+#define NUMTHREADS 256
2c2fa1
+
2c2fa1
+void *
2c2fa1
+thread_function (void *arg)
2c2fa1
+{
2c2fa1
+  pthread_barrier_wait (&barrier);
2c2fa1
+
2c2fa1
+  while (!call_exit)
2c2fa1
+    usleep (1);
2c2fa1
+
2c2fa1
+  _exit (0);
2c2fa1
+  return NULL;
2c2fa1
+}
2c2fa1
+
2c2fa1
+void
2c2fa1
+all_threads_started (void)
2c2fa1
+{
2c2fa1
+  call_exit = 1;
2c2fa1
+}
2c2fa1
+
2c2fa1
+int
2c2fa1
+main (int argc, char **argv)
2c2fa1
+{
2c2fa1
+  pthread_t threads[NUMTHREADS];
2c2fa1
+  int i;
2c2fa1
+
2c2fa1
+  pthread_barrier_init (&barrier, NULL, NUMTHREADS + 1);
2c2fa1
+
2c2fa1
+  for (i = 0; i < NUMTHREADS; ++i)
2c2fa1
+    pthread_create (&threads[i], NULL, thread_function, NULL);
2c2fa1
+
2c2fa1
+  pthread_barrier_wait (&barrier);
2c2fa1
+
2c2fa1
+  all_threads_started ();
2c2fa1
+
2c2fa1
+  for (i = 0; i < NUMTHREADS; ++i)
2c2fa1
+    pthread_join (threads[i], NULL);
2c2fa1
+
2c2fa1
+  return 0;
2c2fa1
+}
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.threads/thread-kills-process.exp
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.threads/thread-kills-process.exp
2c2fa1
@@ -0,0 +1,70 @@
2c2fa1
+# Copyright (C) 2015 Free Software Foundation, Inc.
2c2fa1
+
2c2fa1
+# This program is free software; you can redistribute it and/or modify
2c2fa1
+# it under the terms of the GNU General Public License as published by
2c2fa1
+# the Free Software Foundation; either version 3 of the License, or
2c2fa1
+# (at your option) any later version.
2c2fa1
+#
2c2fa1
+# This program is distributed in the hope that it will be useful,
2c2fa1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+# GNU General Public License for more details.
2c2fa1
+#
2c2fa1
+# You should have received a copy of the GNU General Public License
2c2fa1
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
2c2fa1
+
2c2fa1
+standard_testfile
2c2fa1
+
2c2fa1
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
2c2fa1
+    return -1
2c2fa1
+}
2c2fa1
+
2c2fa1
+clean_restart ${binfile}
2c2fa1
+if {![runto_main]} {
2c2fa1
+    fail "Couldn't run to main"
2c2fa1
+    return
2c2fa1
+}
2c2fa1
+
2c2fa1
+gdb_breakpoint "all_threads_started"
2c2fa1
+
2c2fa1
+gdb_continue_to_breakpoint "all_threads_started"
2c2fa1
+
2c2fa1
+# Update the thread list, otherwise when testing against GDBserver,
2c2fa1
+# GDB won't know about thread 2.  (Only necessary with GDB < 7.9.)
2c2fa1
+gdb_test "info threads" ".*"
2c2fa1
+
2c2fa1
+# Select any thread but the leader.
2c2fa1
+gdb_test "thread 2" ".*" "switch to non-leader thread"
2c2fa1
+
2c2fa1
+# Delete breakpoints so that GDB doesn't switch back the to leader to
2c2fa1
+# step over its breakpoint.
2c2fa1
+delete_breakpoints
2c2fa1
+
2c2fa1
+# Let threads exit the process on next resume.
2c2fa1
+gdb_test "p call_exit = 0" " = 0"
2c2fa1
+
2c2fa1
+# While GDB is busy resuming all threads one by one, one of the
2c2fa1
+# threads should manage to exit the process.  GDB should handle that
2c2fa1
+# gracefully instead of erroring out.
2c2fa1
+#
2c2fa1
+# gdb_continue_to_end doesn't work with GDBserver until the
2c2fa1
+# introduction of the "exit_is_reliable" board variable
2c2fa1
+# (b477a5e649150) in GDB 7.7.
2c2fa1
+#gdb_continue_to_end "" continue 1
2c2fa1
+gdb_test "continue" "$inferior_exited_re normally.*"
2c2fa1
+
2c2fa1
+# On the buggy GDB where the "continue" above would error out, a
2c2fa1
+# subsequent "detach" (e.g., the user tries to quit GDB, and quit
2c2fa1
+# offers to detach) would hit this assertion:
2c2fa1
+#
2c2fa1
+#   linux-nat.c:1869: internal-error: linux_nat_detach: Assertion `num_lwps (GET_PID (inferior_ptid)) == 1' failed.
2c2fa1
+
2c2fa1
+# That was a consequence of the original bug, but let's make sure that
2c2fa1
+# even when "continue" is handled properly, detach doesn't stumble on
2c2fa1
+# anything stale.
2c2fa1
+gdb_test "detach" "The program is not being run\\." \
2c2fa1
+    "detach after exit"
2c2fa1
+
2c2fa1
+# Likewise "continue".
2c2fa1
+gdb_test "continue" "The program is not being run\\." \
2c2fa1
+    "continue after exit"