Blame SOURCES/gdb-rhbz1210135-internal-error-linux_nat_post_attach_wait.patch

7b26da
  NOTE: This patch has been forwardported to RHEL-7.2.  It is originally
7b26da
  from RHEL-6.7.
7b26da
7b26da
  Message-ID: <54E37CE7.50703@redhat.com>
7b26da
  Date: Tue, 17 Feb 2015 17:39:51 +0000
7b26da
  From: Pedro Alves <palves@redhat.com>
7b26da
  To: Sergio Durigan Junior <sergiodj@redhat.com>
7b26da
  Subject: [debug-list] [PATCH] RH BZ #1162264 - gdb/linux-nat.c:1411:
7b26da
   internal-error:,
7b26da
   linux_nat_post_attach_wait: Assertion `pid == new_pid' failed.
7b26da
7b26da
  Hi.
7b26da
7b26da
  Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1162264
7b26da
7b26da
  So I spend a few more hours today trying to reproduce the
7b26da
  EACCES, to no avail.  Also, unfortunately, none of the attach
7b26da
  bugs exposed by attach-many-short-lived-threads.exp test
7b26da
  can explain this.
7b26da
7b26da
  It seems to be that really the best we can do is cope with
7b26da
  the error, like in the patch below.
7b26da
7b26da
  Note that the backtrace at
7b26da
7b26da
   https://bugzilla.redhat.com/show_bug.cgi?id=1162264#c3 :
7b26da
7b26da
  shows that this triggers for the main thread already:
7b26da
7b26da
  ...
7b26da
  #6  0x000000000044fd2e in linux_nat_post_attach_wait (ptid=..., first=1, cloned=0x1d84368,
7b26da
  ...
7b26da
7b26da
  (note "first=1").
7b26da
7b26da
  For upstream, I think linux_nat_attach should be adjusted to work
7b26da
  like gdbserver -- that is, leave the initial waitpid to the main
7b26da
  wait code, like all other events, instead of synchronously
7b26da
  doing waitpid(PID).  That'll get rid of linux_nat_post_attach_wait
7b26da
  altogether.  But that's too invasive for a bug fix.
7b26da
7b26da
  >From 072c61aeb9adc64e1eb45c120061b85fbf6f4d25 Mon Sep 17 00:00:00 2001
7b26da
  From: Pedro Alves <palves@redhat.com>
7b26da
  Date: Tue, 17 Feb 2015 17:11:05 +0000
7b26da
  Subject: [PATCH] RH BZ #1162264 - gdb/linux-nat.c:1411: internal-error:
7b26da
   linux_nat_post_attach_wait: Assertion `pid == new_pid' failed.
7b26da
7b26da
  According to BZ #1162264, it can happen that we manage to attach to a
7b26da
  process, but then waitpid on it fails with EACCES.  That's unexpected,
7b26da
  and gdb hits an assertion.  But given this is an error that is out of
7b26da
  our control, we should handle it gracefully.  I wasn't able to
7b26da
  reproduce the EACCES, but hacking in the error, like:
7b26da
7b26da
  |  --- a/gdb/linux-nat.c
7b26da
  |  +++ b/gdb/linux-nat.c
7b26da
  |  @@ -1409,7 +1409,7 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *cloned,
7b26da
  | 	   *cloned = 1;
7b26da
  | 	 }
7b26da
  | 
7b26da
  |  -  if (new_pid != pid)
7b26da
  |  +  if (new_pid != pid || 1)
7b26da
  | 	 {
7b26da
  | 	   int saved_errno = errno;
7b26da
  | 
7b26da
  |  @@ -1423,6 +1423,7 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *cloned,
7b26da
  | 	   ptrace (PTRACE_DETACH, pid, 0, 0);
7b26da
  | 
7b26da
  | 	   errno = saved_errno;
7b26da
  |  +      errno = EACCES;
7b26da
  | 	   perror_with_name (_("waitpid"));
7b26da
  | 	 }
7b26da
7b26da
  ... I could confirm that the error handling works properly.  On the
7b26da
  EACCES case, we get:
7b26da
7b26da
   (gdb) attach 1202
7b26da
   Attaching to process 1202
7b26da
   Unable to attach: waitpid: Permission denied.
7b26da
   (gdb) info inferiors
7b26da
     Num  Description       Executable
7b26da
   * 1    <null>
7b26da
   (gdb)
7b26da
7b26da
  No test because the conditions that lead to the waitpid error are
7b26da
  unknown.
7b26da
7b26da
  gdb/ChangeLog:
7b26da
  2015-02-17  Pedro Alves  <palves@redhat.com>
7b26da
7b26da
	  * linux-nat.c: Include "exceptions.h".
7b26da
	  (linux_nat_post_attach_wait): If waitpid returns an excepted
7b26da
	  result, detach and error out instead of asserting.
7b26da
	  (linux_nat_attach): Wrap linux_nat_post_attach_wait in TRY_CATCH.
7b26da
	  Mourn inferior and rethrow in case of error while waiting for the
7b26da
	  initial stop.
7b26da
---
7b26da
 gdb/linux-nat.c | 34 +++++++++++++++++++++++++++++++---
7b26da
 1 file changed, 31 insertions(+), 3 deletions(-)
7b26da
7b26da
Index: gdb-7.6.1/gdb/linux-nat.c
7b26da
===================================================================
7b26da
--- gdb-7.6.1.orig/gdb/linux-nat.c
7b26da
+++ gdb-7.6.1/gdb/linux-nat.c
7b26da
@@ -1397,7 +1397,22 @@ linux_nat_post_attach_wait (ptid_t ptid,
7b26da
       *cloned = 1;
7b26da
     }
7b26da
 
7b26da
-  gdb_assert (pid == new_pid);
7b26da
+  if (new_pid != pid)
7b26da
+    {
7b26da
+      int saved_errno = errno;
7b26da
+
7b26da
+      /* Unexpected waitpid result.  EACCES has been observed on RHEL
7b26da
+	 6.5 (RH BZ #1162264).  This is most likely a kernel bug, thus
7b26da
+	 out of our control, so treat it as invalid input.  The LWP's
7b26da
+	 state is indeterminate at this point, so best we can do is
7b26da
+	 error out, otherwise we'd probably end up wedged later on.
7b26da
+
7b26da
+	 In case we're still attached.  */
7b26da
+      ptrace (PTRACE_DETACH, pid, 0, 0);
7b26da
+
7b26da
+      errno = saved_errno;
7b26da
+      perror_with_name (_("waitpid"));
7b26da
+    }
7b26da
 
7b26da
   if (!WIFSTOPPED (status))
7b26da
     {
7b26da
@@ -1621,7 +1636,7 @@ static void
7b26da
 linux_nat_attach (struct target_ops *ops, char *args, int from_tty)
7b26da
 {
7b26da
   struct lwp_info *lp;
7b26da
-  int status;
7b26da
+  int status = 0;
7b26da
   ptid_t ptid;
7b26da
   volatile struct gdb_exception ex;
7b26da
 
7b26da
@@ -1659,8 +1674,19 @@ linux_nat_attach (struct target_ops *ops
7b26da
   /* Add the initial process as the first LWP to the list.  */
7b26da
   lp = add_initial_lwp (ptid);
7b26da
 
7b26da
-  status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->cloned,
7b26da
-				       &lp->signalled);
7b26da
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
7b26da
+    {
7b26da
+      status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->cloned,
7b26da
+					   &lp->signalled);
7b26da
+    }
7b26da
+  if (ex.reason < 0)
7b26da
+    {
7b26da
+      target_terminal_ours ();
7b26da
+      target_mourn_inferior ();
7b26da
+
7b26da
+      error (_("Unable to attach: %s"), ex.message);
7b26da
+    }
7b26da
+
7b26da
   if (!WIFSTOPPED (status))
7b26da
     {
7b26da
       if (WIFEXITED (status))