diff --git a/gdb/common/common-exceptions.h b/gdb/common/common-exceptions.h
index a32e6f9..1a13f18 100644
--- a/gdb/common/common-exceptions.h
+++ b/gdb/common/common-exceptions.h
@@ -93,6 +93,9 @@ enum errors {
      aborted as the inferior state is no longer valid.  */
   TARGET_CLOSE_ERROR,
 
+  /* The thread is gone.  */
+  THREAD_NOT_FOUND_ERROR,
+
   /* An undefined command was executed.  */
   UNDEFINED_COMMAND_ERROR,
 
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 48d905b..f9c4079 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -28,6 +28,7 @@
 #include "nat/linux-ptrace.h"
 #include "nat/linux-procfs.h"
 #include "nat/linux-personality.h"
+#include "nat/ptrace-utils.h"
 #include <signal.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
@@ -3378,13 +3379,12 @@ stop_all_lwps (int suspend, struct lwp_info *except)
     }
 }
 
-/* Resume execution of the inferior process.
-   If STEP is nonzero, single-step it.
-   If SIGNAL is nonzero, give it that signal.  */
+/* Like linux_resume_one_lwp but throws THREAD_NOT_FOUND_ERROR if the
+   LWP has disappeared (ptrace returns ESRCH).  */
 
 static void
-linux_resume_one_lwp (struct lwp_info *lwp,
-		      int step, int signal, siginfo_t *info)
+linux_resume_one_lwp_throw (struct lwp_info *lwp,
+			    int step, int signal, siginfo_t *info)
 {
   struct thread_info *thread = get_lwp_thread (lwp);
   struct thread_info *saved_thread;
@@ -3576,18 +3576,40 @@ linux_resume_one_lwp (struct lwp_info *lwp,
 
   current_thread = saved_thread;
   if (errno)
-    {
-      /* ESRCH from ptrace either means that the thread was already
-	 running (an error) or that it is gone (a race condition).  If
-	 it's gone, we will get a notification the next time we wait,
-	 so we can ignore the error.  We could differentiate these
-	 two, but it's tricky without waiting; the thread still exists
-	 as a zombie, so sending it signal 0 would succeed.  So just
-	 ignore ESRCH.  */
-      if (errno == ESRCH)
-	return;
+    throw_ptrace_error ("resuming thread");
+}
 
-      perror_with_name ("ptrace");
+/* Resume execution of LWP.  If STEP is nonzero, single-step it.  If
+   SIGNAL is nonzero, give it that signal.  No error is throw if the
+   LWP disappears while we try to resume it, no error is thrown.  */
+
+static void
+linux_resume_one_lwp (struct lwp_info *lwp,
+		      int step, int signal, siginfo_t *info)
+{
+  struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      linux_resume_one_lwp_throw (lwp, step, signal, info);
+    }
+  if (ex.reason < 0)
+    {
+      if (ex.error == THREAD_NOT_FOUND_ERROR)
+	{
+	  /* We got an ESRCH while resuming the LWP.  ESRCH from
+	     ptrace either means that the thread was already running
+	     (an error/bug) or that it is gone (a race condition, e.g,
+	     another thread exited the whole process.), or it was
+	     killed by SIGKILL.  If it's gone, we will get a
+	     notification the next time we wait, so we can ignore the
+	     error.  We could differentiate these, but it's tricky
+	     without waiting; the thread still exists as a zombie, so
+	     sending it signal 0 would succeed.  So just ignore
+	     ESRCH.  */
+	}
+      else
+	throw_exception (ex);
     }
 }
 
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 20fe533..6bb62fd 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1504,7 +1504,7 @@ linux_nat_detach (struct target_ops *ops, const char *args, int from_tty)
    single-step it.  If SIGNAL is nonzero, give it that signal.  */
 
 static void
-linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
+linux_resume_one_lwp_throw (struct lwp_info *lp, int step, enum gdb_signal signo)
 {
   lp->step = step;
 
@@ -1528,6 +1528,36 @@ linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
   registers_changed_ptid (lp->ptid);
 }
 
+static void
+linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
+{
+  struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      linux_resume_one_lwp_throw (lp, step, signo);
+    }
+  if (ex.reason < 0)
+    {
+      if (ex.error == THREAD_NOT_FOUND_ERROR)
+	{
+	  /* We got an ESRCH while resuming the LWP.  ESRCH from
+	     ptrace either means that the thread was already running
+	     (an error/bug) or that it is gone (a race condition, e.g,
+	     another thread exited the whole process.), or it was
+	     killed by SIGKILL.  If it's gone, we will get a
+	     notification the next time we wait, so we can ignore the
+	     error.  We could differentiate these, but it's tricky
+	     without waiting; the thread still exists as a zombie, so
+	     sending it signal 0 would succeed.  So just ignore
+	     ESRCH.  */
+	}
+      else
+	throw_exception (ex);
+    }
+}
+
+
 /* Resume LP.  */
 
 static void
diff --git a/gdb/nat/ptrace-utils.c b/gdb/nat/ptrace-utils.c
index a3dc9b5..ca59454 100644
--- a/gdb/nat/ptrace-utils.c
+++ b/gdb/nat/ptrace-utils.c
@@ -25,5 +25,25 @@
 void
 throw_ptrace_error (const char *string)
 {
-  perror_with_name (string);
+  enum errors errcode;
+
+  switch (errno)
+    {
+    case ESRCH:
+      /* This either means that:
+
+	 - the thread was already running (a GDB error/bug).
+
+	 - the thread is gone, a race condition.  E.g, another thread
+	   was set running and it exited the whole process, or the
+	   process was killed by a SIGKILL.
+
+	 Assume the latter.  */
+      errcode = THREAD_NOT_FOUND_ERROR;
+      break;
+    default:
+      errcode = GENERIC_ERROR;
+      break;
+    }
+  throw_perror_with_name (errcode, string);
 }
