rpms/gdb/devel gdb-6.6-bz233852-attach-signalled.patch, 1.1, 1.2 gdb.spec, 1.243, 1.244

Jan Kratochvil (jkratoch) fedora-extras-commits at redhat.com
Sun Sep 16 22:34:38 UTC 2007


Author: jkratoch

Update of /cvs/pkgs/rpms/gdb/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv29194

Modified Files:
	gdb-6.6-bz233852-attach-signalled.patch gdb.spec 
Log Message:
* Sun Sep 16 2007 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.6-27
- Fix attaching to stopped processes and/or pending signals.


gdb-6.6-bz233852-attach-signalled.patch:

Index: gdb-6.6-bz233852-attach-signalled.patch
===================================================================
RCS file: /cvs/pkgs/rpms/gdb/devel/gdb-6.6-bz233852-attach-signalled.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- gdb-6.6-bz233852-attach-signalled.patch	20 Jun 2007 14:25:46 -0000	1.1
+++ gdb-6.6-bz233852-attach-signalled.patch	16 Sep 2007 22:34:35 -0000	1.2
@@ -1,94 +1,151 @@
-diff -u -rup gdb-6.6-orig/gdb/inf-ptrace.c gdb-6.6/gdb/inf-ptrace.c
---- gdb-6.6-orig/gdb/inf-ptrace.c	2006-01-24 23:34:34.000000000 +0100
-+++ gdb-6.6/gdb/inf-ptrace.c	2007-06-06 13:33:11.000000000 +0200
-@@ -38,6 +38,9 @@
- 
- /* HACK: Save the ptrace ops returned by inf_ptrace_target.  */
- static struct target_ops *ptrace_ops_hack;
-+
-+/* Stored PID of the process being stopped during attach.  */
-+static pid_t stopped_pid;
- 
- 
- #ifdef PT_GET_PROCESS_STATE
-@@ -69,14 +72,20 @@ inf_ptrace_follow_fork (struct target_op
+2007-07-01  Jan Kratochvil  <jan.kratochvil at redhat.com>
+
+	* linux-nat.h (struct lwp_info): New field WAS_STOPPED.
+	* linux-nat.c (STRINGIFY, STRINGIFY_ARG): New macros.
+	(kill_lwp): New declaration.
+	(linux_ptrace_post_attach, pid_is_stopped): New function.
+	(linux_child_follow_fork): New comment about WAS_STOPPED.
+	(lin_lwp_attach_lwp): Variable PID removed.  Part replaced by a call to
+	LINUX_PTRACE_POST_ATTACH.
+	(linux_nat_attach): Likewise.
+	(linux_nat_detach): Optionally stop the detached process.
+	(linux_nat_resume): Clear WAS_STOPPED if appropriate.
+	* NEWS: Document the new behaviour.
+
+2007-06-30  Jan Kratochvil  <jan.kratochvil at redhat.com>
+
+	* gdb.threads/attach-into-signal.c, gdb.threads/attach-into-signal.exp,
+	gdb.threads/attach-stopped.c, gdb.threads/attach-stopped.exp: New files.
+
+2007-06-30  Jan Kratochvil  <jan.kratochvil at redhat.com>
+
+	* gdb.texinfo (Attach): Document the ATTACH and DETACH commands for
+	stopped processes.  Document the messages on the seen pending signals.
+
+[ Backport for GDB-6.6. ]
+
+--- ./gdb/NEWS	21 Jun 2007 15:18:50 -0000	1.232
++++ ./gdb/NEWS	30 Jun 2007 16:27:37 -0000
+@@ -44,6 +44,9 @@ segment base addresses (rather than offs
+ * The /i format now outputs any trailing branch delay slot instructions 
+ immediately following the last instruction within the count specified.
+ 
++* On GNU/Linux, stopped processes may get attached to now.  Signals being
++delivered at the time of the attach command no longer get lost.
++
+ * New commands
+ 
+ set remoteflow
+--- gdb-6.6/gdb/linux-nat.c-orig-orig	2007-09-16 20:57:13.000000000 +0200
++++ gdb-6.6/gdb/linux-nat.c	2007-09-16 21:02:28.000000000 +0200
+@@ -87,6 +87,12 @@
+ #define __WALL          0x40000000 /* Wait for any child.  */
+ #endif
  
-   if (follow_child)
-     {
-+      unsigned long sig = 0;
++#define STRINGIFY_ARG(x) #x
++#define STRINGIFY(x) STRINGIFY_ARG (x)
 +
-       inferior_ptid = pid_to_ptid (fpid);
-       detach_breakpoints (pid);
++static int linux_ptrace_post_attach (struct lwp_info *lp);
++static int kill_lwp (int lwpid, int signo);
++
+ /* The single-threaded native GNU/Linux target_ops.  We save a pointer for
+    the use of the multi-threaded target.  */
+ static struct target_ops *linux_ops;
+@@ -533,6 +539,11 @@ child_follow_fork (struct target_ops *op
+ 	}
+       else
+ 	{
++	  /* We should check LP->WAS_STOPPED and detach it stopped accordingly.
++	     In this point of code it cannot be 1 as we would not get FORK
++	     executed without CONTINUE first which resets LP->WAS_STOPPED.
++	     We would have to first TARGET_STOP and WAITPID it as with running
++	     inferior PTRACE_DETACH, SIGSTOP will ignore the signal.  */
+ 	  target_detach (NULL, 0);
+ 	}
+ 
+@@ -992,7 +1003,6 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
+      to happen.  */
+   if (GET_LWP (ptid) != GET_PID (ptid) && lp == NULL)
+     {
+-      pid_t pid;
+       int status;
  
-       /* Reset breakpoints in the child as appropriate.  */
-       follow_inferior_reset_breakpoints ();
+       if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
+@@ -1002,45 +1012,23 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
+ 	     creation is interrupted; as of Linux 2.6.19, a kernel
+ 	     bug may place threads in the thread list and then fail
+ 	     to create them.  */
+-	  warning (_("Can't attach %s: %s"), target_pid_to_str (ptid),
+-		   safe_strerror (errno));
+-	  return -1;
++	  error (_("Can't attach %s: %s"), target_pid_to_str (ptid),
++		 safe_strerror (errno));
+ 	}
  
--      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
--	perror_with_name (("ptrace"));
-+      /* Stop the process again if it was stopped during the attachment.  */
-+      if (pid == stopped_pid)
-+	sig = target_signal_to_host (TARGET_SIGNAL_STOP));
-+
-+      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, (void *) sig) == -1)
-+	perror_with_name (("ptrace PT_DETACH"));
+       if (lp == NULL)
+ 	lp = add_lwp (ptid);
+ 
+-      if (debug_linux_nat)
+-	fprintf_unfiltered (gdb_stdlog,
+-			    "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
+-			    target_pid_to_str (ptid));
+-
+-      pid = my_waitpid (GET_LWP (ptid), &status, 0);
+-      if (pid == -1 && errno == ECHILD)
+-	{
+-	  /* Try again with __WCLONE to check cloned processes.  */
+-	  pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
+-	  if (pid == -1 && errno == ECHILD)
+-	    error (_("Can't attach %s (%s) - possible SELinux denial,"
+-		     " check your /var/log/messages for `avc: denied'"),
+-		   target_pid_to_str (ptid), safe_strerror (errno));
+-	  lp->cloned = 1;
++      status = linux_ptrace_post_attach (lp);
++      if (status != 0)
++        {
++	  error (_("Thread %s exited: %s"), target_pid_to_str (ptid),
++		 status_to_str (status));
+ 	}
+ 
+-      gdb_assert (pid == GET_LWP (ptid)
+-		  && WIFSTOPPED (status) && WSTOPSIG (status));
+-
+-      target_post_attach (pid);
++      target_post_attach (GET_LWP (ptid));
+ 
+       lp->stopped = 1;
+-
+-      if (debug_linux_nat)
+-	{
+-	  fprintf_unfiltered (gdb_stdlog,
+-			      "LLAL: waitpid %s received %s\n",
+-			      target_pid_to_str (ptid),
+-			      status_to_str (status));
+-	}
      }
    else
      {
-@@ -173,6 +182,21 @@ inf_ptrace_mourn_inferior (void)
-   generic_mourn_inferior ();
+@@ -1061,11 +1049,172 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
+   return 0;
  }
  
-+/* Wrapper function for waitpid which handles EINTR.  */
++/* Detect `T (stopped)' in `/proc/PID/status'.
++   Other states including `T (tracing stop)' are reported as false.  */
 +
 +static int
-+my_waitpid (int pid, int *status, int flags)
++pid_is_stopped (pid_t pid)
 +{
-+  int ret;
-+  do
-+    {
-+      ret = waitpid (pid, status, flags);
-+    }
-+  while (ret == -1 && errno == EINTR);
-+
-+  return ret;
-+}
-+
- /* Attach to the process specified by ARGS.  If FROM_TTY is non-zero,
-    be chatty about it.  */
- 
-@@ -180,8 +204,14 @@ static void
- inf_ptrace_attach (char *args, int from_tty)
- {
-   char *exec_file;
--  pid_t pid;
-+  pid_t pid, got_pid;
-   char *dummy;
-+  int status;
-+  unsigned long sig;
 +  FILE *status_file;
-+  char name[40];
 +  char buf[100]; 
-+  int sigstop = target_signal_to_host (TARGET_SIGNAL_STOP);
- 
-   if (!args)
-     error_no_arg (_("process-id to attach"));
-@@ -210,11 +240,64 @@ inf_ptrace_attach (char *args, int from_
-     }
- 
- #ifdef PT_ATTACH
-+  stopped_pid = 0;
-+  /* There is a small moment after PTRACE_ATTACH where PTRACE_CONT will
-+     succeed only for originally stopped processes.  Unfortunately in a moment
-+     PTRACE_ATTACH will deliver its SIGSTOP and PTRACE_CONT shows no difference
-+     since that moment.
-+     "/proc/%d/status" is also a race but it is safe for unstopped cases.  */
-+  sprintf (name, "/proc/%d/status", (int) pid);
-+  status_file = fopen (name, "r");
++  int retval = 0;
++
++  snprintf (buf, sizeof (buf), "/proc/%d/status", (int) pid);
++  status_file = fopen (buf, "r");
 +  if (status_file != NULL)
 +    {
 +      int have_state = 0;
 +
-+      while (fgets (buf, 100, status_file))
++      while (fgets (buf, sizeof (buf), status_file))
 +	{
 +	  if (strncmp (buf, "State:", 6) == 0)
 +	    {
@@ -96,199 +153,153 @@
 +	      break;
 +	    }
 +	} 
-+      if (have_state != 0 && strstr (buf, "T (stopped)") != NULL)
-+	stopped_pid = pid;
++      if (have_state && strstr (buf, "T (stopped)") != NULL)
++	retval = 1;
 +      fclose (status_file);
 +    }
++  return retval;
++}
++
++/* Handle the processing after PTRACE_ATTACH, the first WAITPID -> SIGSTOP.
++   Returns STATUS if the thread has exited, 0 otherwise.
++   Sets LP->WAS_STOPPED if the process was originally stopped.
++   Sets LP->CLONED if the given LWP is not the thread leader.
++
++   Scenario for a standard unstopped inferior:
++    * `S (sleeping)' or `R (running)' or similiar states.
++    * PTRACE_ATTACH is called.
++    * `S (sleeping)' (or similiar) for some while.
++    * `T (tracing stop)'.
++    * WAITPID succeeds here returning SIGSTOP (signalled by PTRACE_ATTACH).
++
++   Scenario for a formerly stopped inferior:
++    * `T (stopped)'.
++    * PTRACE_ATTACH is called.
++    * `T (stopped)' would stay indefinitely
++      Note since this moment the `TracerPid' field gets filled
++      (by PTRACE_ATTACH), it is no longer just the common `T (stopped)' state.
++       * If no one did WAITPID since sending SIGSTOP our WAITPID would return
++         SIGSTOP.  The state still would not turn to `T (tracing stop)'.
++       * Usually its original parent (before PTRACE_ATTACH was applied) already
++         did WAITPID.  The original parent already received our SIGSTOP
++         sinalled by our PTRACE_ATTACH.
++         In this case our own WAITPID would hang.  Therefore...
++    * ... we do artificial: tkill (SIGCONT);
++      `PTRACE_CONT, SIGSTOP' does not work in 100% cases as sometimes SIGSTOP
++      gets remembered by kernel during the first PTRACE_CONT later and we get
++      spurious SIGSTOP event.  Expecting the signal may get delivered to
++      a different task of the thread group.
++      `kill_lwp (SIGSTOP)' has no effect in this moment (it is already stopped).
++    * WAITPID returns the artifical SIGCONT.
++      (The possibly pending SIGSTOP gets vanished by specifically SIGCONT.)
++    * State turns `T (tracing stop)'.
++   In this moment everything is almost fine but we need a workaround as final
++   `PTRACE_DETACH, SIGSTOP' would leave the process unstopped otherwise:
++    * tkill (SIGSTOP);
++    * `PTRACE_CONT, 0'
++    * WAITPID returns the artifical SIGSTOP.
++
++   With the pending (unwaited for) SIGSTOP the artifical signal effects are:
++   kill (SIGSTOP)
++   PTRACE_ATTACH
++    /-tkill (SIGCONT), WAITPID: SIGCONT, WAITPID: hang !
++   //-tkill (SIGCONT), WAITPID: SIGCONT, PTRACE_CONT (SIG_0), WAITPID: wait (OK)
++   \\-tkill (SIGALRM), WAITPID: SIGSTOP, WAITPID: hang !
++    \-tkill (SIGALRM), WAITPID: SIGSTOP, PTRACE_CONT (SIG_0), WAITPID: SIGALRM !
++   Therefore we signal artifical SIGCONT and stop waiting after its reception.
++
++   For the detection whether the process was formerly stopped we need to
++   read `/proc/PID/status'.  `PTRACE_CONT, SIGSTOP' returns ESRCH
++   for `S (sleeping)' and succeeds for `T (stopped)' but it unfortunately
++   succeeds even for `T (tracing stop)'.  Depending on PTRACE_CONT, SIGSTOP
++   success value for formerly stopped processes would mean a race condition
++   as we would get false stopped processes detection if we get too slow.
++
++   `waitid (..., WSTOPPED)' hangs the same way as WAITPID.
++
++   Signals get queued for WAITPID.  PTRACE_ATTACH (or TKILL) enqueues SIGSTOP
++   there but WAITPID may return an already pending signal.
++   Redeliver it by PTRACE_CONT, SIGxxx as otherwise it would get lost.
++   Similiar processing is being done in this file by WAIT_LWP.  */
++
++static int
++linux_ptrace_post_attach (struct lwp_info *lp)
++{
++  ptid_t ptid = lp->ptid;
++  unsigned long sig;
++
++  if (debug_linux_nat)
++    fprintf_unfiltered (gdb_stdlog,
++			"LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
++			target_pid_to_str (ptid));
++
++  lp->was_stopped = pid_is_stopped (GET_LWP (ptid));
++  if (lp->was_stopped)
++    {
++      if (kill_lwp (GET_LWP (ptid), SIGCONT) != 0)
++	perror_with_name (("kill_lwp (SIGCONT)"));
++    }
 +
-   errno = 0;
-   ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
-   if (errno != 0)
-     perror_with_name (("ptrace"));
-   attach_flag = 1;
-+
-+  /* Deliver one SIGSTOP just for sure.
-+     If the process was already stopped AND some other process (like shell)
-+     has already waited for it we would get stuck in waitpid ().  */
-+  sig = sigstop;
-+  do
++  for (;;)
 +    {
-+      if (sig != sigstop)
-+	printf_unfiltered (_("Redelivering pending %s.\n"),
-+		       target_signal_to_string (target_signal_from_host (sig)));
-+      errno = 0;
-+      ptrace (PT_CONTINUE, pid, (PTRACE_TYPE_ARG3)1, (void *) sig);
-+      /* For unstopped processes the preventive signal may ESRCH.  */
-+      if (errno != 0 && sig != sigstop)
-+	perror_with_name ("ptrace PT_CONTINUE");
++      pid_t pid;
++      int status;
++
++      pid = my_waitpid (GET_LWP (ptid), &status, 0);
++      if (pid == -1 && errno == ECHILD)
++	{
++	  /* Try again with __WCLONE to check cloned processes.  */
++	  pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
++	  lp->cloned = 1;
++	}
++      gdb_assert (pid == GET_LWP (ptid));
 +
-+      got_pid = my_waitpid (pid, &status, 0);
-+      gdb_assert (got_pid == pid);
++      if (debug_linux_nat)
++	{
++	  fprintf_unfiltered (gdb_stdlog,
++			      "LLAL: waitpid %s received %s\n",
++			      target_pid_to_str (ptid),
++			      status_to_str (status));
++	}
 +
 +      /* Check if the thread has exited.  */
 +      if (WIFEXITED (status) || WIFSIGNALED (status))
-+	error (_("Program %s exited.\n"),
-+	       target_pid_to_str (pid_to_ptid (pid)));
++        return status;
 +      gdb_assert (WIFSTOPPED (status));
 +      sig = WSTOPSIG (status);
 +      gdb_assert (sig != 0);
-+    }
-+  while (sig != sigstop);
- #else
-   error (_("This system does not support attaching to a process"));
- #endif
-@@ -240,14 +323,16 @@ inf_ptrace_post_attach (int pid)
- 
- #endif
- 
--/* Detach from the inferior, optionally passing it the signal
--   specified by ARGS.  If FROM_TTY is non-zero, be chatty about it.  */
-+/* Detach from the inferior.  If FROM_TTY is non-zero, be chatty about it.  */
- 
- static void
- inf_ptrace_detach (char *args, int from_tty)
- {
-   pid_t pid = ptid_get_pid (inferior_ptid);
--  int sig = 0;
-+  unsigned long sig = 0;
++      if (sig == SIGSTOP)
++        break;
 +
-+  if (args)
-+    error (_("Too many arguments"));
- 
-   if (from_tty)
-     {
-@@ -258,18 +343,19 @@ inf_ptrace_detach (char *args, int from_
- 			 target_pid_to_str (pid_to_ptid (pid)));
-       gdb_flush (gdb_stdout);
-     }
--  if (args)
--    sig = atoi (args);
- 
- #ifdef PT_DETACH
-   /* We'd better not have left any breakpoints in the program or it'll
-      die when it hits one.  Also note that this may only work if we
-      previously attached to the inferior.  It *might* work if we
-      started the process ourselves.  */
-+  /* Stop the process again if it was stopped during the attachment.  */
-+  if (pid == stopped_pid)
-+    sig = target_signal_to_host (TARGET_SIGNAL_STOP);
-   errno = 0;
--  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
-+  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, (void *) sig);
-   if (errno != 0)
--    perror_with_name (("ptrace"));
-+    perror_with_name (("ptrace PT_DETACH"));
-   attach_flag = 0;
- #else
-   error (_("This system does not support detaching from a process"));
-@@ -324,6 +410,12 @@ inf_ptrace_resume (ptid_t ptid, int step
-        single-threaded processes, so simply resume the inferior.  */
-     pid = ptid_get_pid (inferior_ptid);
- 
-+  /* At this point, we are going to resume the inferior and if we
-+     have attached to a stopped process, we no longer should leave
-+     it as stopped if the user detaches.  */
-+  if (!step && pid == stopped_pid)
-+    stopped_pid = 0;
-+
-   if (step)
-     {
-       /* If this system does not support PT_STEP, a higher level
-diff -u -rup gdb-6.6-orig/gdb/linux-nat.c gdb-6.6/gdb/linux-nat.c
---- gdb-6.6-orig/gdb/linux-nat.c	2007-06-06 13:30:52.000000000 +0200
-+++ gdb-6.6/gdb/linux-nat.c	2007-06-06 13:57:18.000000000 +0200
-@@ -994,6 +994,7 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
-     {
-       pid_t pid;
-       int status;
-+      unsigned long sig;
- 
-       if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
- 	{
-@@ -1015,32 +1016,54 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
- 			    "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
- 			    target_pid_to_str (ptid));
- 
--      pid = my_waitpid (GET_LWP (ptid), &status, 0);
--      if (pid == -1 && errno == ECHILD)
-+      sig = SIGSTOP;
-+      do
- 	{
--	  /* Try again with __WCLONE to check cloned processes.  */
--	  pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
-+	  if (sig != SIGSTOP)
-+	    printf_unfiltered (_("Redelivering pending %s.\n"),
-+		       target_signal_to_string (target_signal_from_host (sig)));
-+	  /* For unstopped processes the preventive signal may ESRCH.  */
-+	  if (ptrace (PTRACE_CONT, GET_LWP (ptid), (PTRACE_TYPE_ARG3)1,
-+		      (void *) sig) != 0 && sig != SIGSTOP)
-+	    perror_with_name ("ptrace");
++      /* As the second signal for stopped processes we send SIGSTOP.  */
++      if (lp->was_stopped && sig == SIGCONT)
++	sig = SIGSTOP;
++
++      printf_unfiltered (_("Redelivering pending %s.\n"),
++		 target_signal_to_string (target_signal_from_host (sig)));
++      if (sig == SIGSTOP)
++	{
++	  if (kill_lwp (GET_LWP (ptid), sig) != 0)
++	    perror_with_name (("kill_lwp"));
++	  /* We now must resume the inferior to get SIGSTOP delivered.  */
++	  sig = 0;
++	}
++      if (ptrace (PTRACE_CONT, GET_LWP (ptid), NULL, (void *) sig) != 0)
++	perror_with_name (("ptrace"));
++    }
 +
-+	  pid = my_waitpid (GET_LWP (ptid), &status, 0);
- 	  if (pid == -1 && errno == ECHILD)
--	    error (_("Can't attach %s (%s) - possible SELinux denial,"
--		     " check your /var/log/messages for `avc: denied'"),
--		   target_pid_to_str (ptid), safe_strerror (errno));
--	  lp->cloned = 1;
--	}
-+	    {
-+	      /* Try again with __WCLONE to check cloned processes.  */
-+	      pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
-+	      if (pid == -1 && errno == ECHILD)
-+		error (_("Can't attach %s (%s) - possible SELinux denial,"
-+			 " check your /var/log/messages for `avc: denied'"),
-+		       target_pid_to_str (ptid), safe_strerror (errno));
-+	      lp->cloned = 1;
-+	    }
-+	  gdb_assert (pid == GET_LWP (ptid));
- 
--      gdb_assert (pid == GET_LWP (ptid)
--		  && WIFSTOPPED (status) && WSTOPSIG (status));
-+	  if (debug_linux_nat)
-+	    {
-+	      fprintf_unfiltered (gdb_stdlog,
-+				  "LLAL: waitpid %s received %s\n",
-+				  target_pid_to_str (ptid),
-+				  status_to_str (status));
-+	    }
++  return 0;
++}
 +
-+	  /* Check if the thread has exited.  */
-+	  if (WIFEXITED (status) || WIFSIGNALED (status))
-+	    {
-+	      warning (_("Thread %s exited: %s"), target_pid_to_str (ptid),
-+		       status_to_str (status));
-+	      return -1;
-+	    }
-+	  gdb_assert (WIFSTOPPED (status));
-+	  sig = WSTOPSIG (status);
-+	  gdb_assert (sig != 0);
-+	}
-+      while (sig != SIGSTOP);
- 
-       target_post_attach (pid);
- 
-       lp->stopped = 1;
--
--      if (debug_linux_nat)
--	{
--	  fprintf_unfiltered (gdb_stdlog,
--			      "LLAL: waitpid %s received %s\n",
--			      target_pid_to_str (ptid),
--			      status_to_str (status));
--	}
-     }
-   else
-     {
-@@ -1065,8 +1088,6 @@ static void
+ static void
  linux_nat_attach (char *args, int from_tty)
  {
    struct lwp_info *lp;
 -  pid_t pid;
--  int status;
+   int status;
  
    /* FIXME: We should probably accept a list of process id's, and
-      attach all of them.  */
-@@ -1076,22 +1097,6 @@ linux_nat_attach (char *args, int from_t
+@@ -1076,21 +1225,12 @@ linux_nat_attach (char *args, int from_t
    inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
    lp = add_lwp (inferior_ptid);
  
@@ -307,11 +318,16 @@
 -
 -  gdb_assert (pid == GET_PID (inferior_ptid)
 -	      && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
--
++  status = linux_ptrace_post_attach (lp);
++  if (status != 0)
++    error (_("Program %s exited: %s\n"), target_pid_to_str (inferior_ptid),
++	   status_to_str (status));
++  if (lp->cloned)
++    warning (_("%s is a cloned process"), target_pid_to_str (inferior_ptid));
+ 
    lp->stopped = 1;
  
-   /* Fake the SIGSTOP that core GDB expects.  */
-@@ -1099,8 +1104,8 @@ linux_nat_attach (char *args, int from_t
+@@ -1099,8 +1239,8 @@ linux_nat_attach (char *args, int from_t
    lp->resumed = 1;
    if (debug_linux_nat)
      {
@@ -322,26 +338,44 @@
      }
  }
  
-diff -u -rup gdb-6.6-orig/gdb/target.h gdb-6.6/gdb/target.h
---- gdb-6.6-orig/gdb/target.h	2007-06-06 13:30:52.000000000 +0200
-+++ gdb-6.6/gdb/target.h	2007-06-06 13:33:11.000000000 +0200
-@@ -529,9 +529,9 @@ void target_close (struct target_ops *ta
-    to the `attach' command by the user.  This routine can be called
-    when the target is not on the target-stack, if the target_can_run
-    routine returns 1; in that case, it must push itself onto the stack.
--   Upon exit, the target should be ready for normal operations, and
--   should be ready to deliver the status of the process immediately
--   (without waiting) to an upcoming target_wait call.  */
-+   Upon exit, the target should be ready for normal operations.
-+   The status of the inferior is already processed and possibly pending
-+   signals redelivered.  */
- 
- #define	target_attach(args, from_tty)	\
-      (*current_target.to_attach) (args, from_tty)
-diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.c gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.c
---- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.c	2007-06-06 16:36:34.000000000 +0200
-+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.c	2007-06-06 13:33:11.000000000 +0200
-@@ -0,0 +1,65 @@
+@@ -1173,6 +1313,9 @@ linux_nat_detach (char *args, int from_t
+ 
+   trap_ptid = null_ptid;
+ 
++  if (lwp_list->was_stopped)
++    args = STRINGIFY (SIGSTOP);
++
+   /* Destroy LWP info; it's no longer valid.  */
+   init_lwp_list ();
+ 
+@@ -1310,6 +1453,12 @@ linux_nat_resume (ptid_t ptid, int step_
+       lp->stopped = 0;
+     }
+ 
++  /* At this point, we are going to resume the inferior and if we
++     have attached to a stopped process, we no longer should leave
++     it as stopped if the user detaches.  */
++  if (!step && lp != NULL)
++    lp->was_stopped = 0;
++
+   if (resume_all)
+     iterate_over_lwps (resume_callback, NULL);
+ 
+--- ./gdb/linux-nat.h	10 May 2007 21:36:00 -0000	1.18
++++ ./gdb/linux-nat.h	29 Jun 2007 22:06:05 -0000
+@@ -42,6 +42,9 @@ struct lwp_info
+   /* Non-zero if this LWP is stopped.  */
+   int stopped;
+ 
++  /* Non-zero if this LWP was stopped by SIGSTOP before attaching.  */
++  int was_stopped;
++
+   /* Non-zero if this LWP will be/has been resumed.  Note that an LWP
+      can be marked both as stopped and resumed at the same time.  This
+      happens if we try to resume an LWP that has a wait status
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ ./gdb/testsuite/gdb.threads/attach-into-signal.c	29 Jun 2007 22:06:05 -0000
+@@ -0,0 +1,70 @@
 +/* This testcase is part of GDB, the GNU debugger.
 +
 +   Copyright 2007 Free Software Foundation, Inc.
@@ -385,6 +419,11 @@
 +
 +  raise (SIGALRM);
 +
++  /* It is an upstream kernel bug (2.6.22-rc4-git7.x86_64, PREEMPT, SMP).
++     We never get here without ptrace(2) but we get while under ptrace(2).  */
++  for (;;)
++    pause ();
++
 +  abort ();
 +  /* NOTREACHED */
 +  return NULL;
@@ -407,10 +446,9 @@
 +
 +  return 0;
 +}
-diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.exp gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.exp
---- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.exp	2007-06-06 16:36:34.000000000 +0200
-+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.exp	2007-06-06 13:33:11.000000000 +0200
-@@ -0,0 +1,153 @@
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ ./gdb/testsuite/gdb.threads/attach-into-signal.exp	29 Jun 2007 22:06:06 -0000
+@@ -0,0 +1,176 @@
 +# Copyright 2007
 +
 +# This program is free software; you can redistribute it and/or modify
@@ -472,12 +510,33 @@
 +
 +    # linux-2.6.20.4.x86_64 had maximal attempt # 20 in 4 test runs.
 +    set attempts 100
-+    set attempt 0
++    set attempt 1
 +    set passes 1
-+    while { $passes < 3 && $attempt < $attempts } {
++    while { $passes < 3 && $attempt <= $attempts } {
 +
 +	# Start with clean gdb
 +	gdb_exit
++
++	set stoppedtry 0
++	while { $stoppedtry < 10 } {
++	    set fileid [open /proc/${testpid}/status r];
++	    gets $fileid line1;
++	    gets $fileid line2;
++	    close $fileid;
++
++	    if {![string match "*(stopped)*" $line2]} {
++		# No PASS message as we may be looping in multiple attempts.
++		break
++	    }
++	    sleep 1
++	    set stoppedtry [expr $stoppedtry + 1]
++	}
++	if { $stoppedtry >= 10 } {
++	    verbose -log $line2
++	    set test "$threadtype: process is still running on the attempt # $attempt of $attempts"
++	    break
++	}
++
 +	gdb_start
 +	gdb_reinitialize_dir $srcdir/$subdir
 +	gdb_load ${binfile}
@@ -528,7 +587,11 @@
 +	}
 +    }
 +    if {$passes < 3} {
-+	fail $test
++	if {$attempt > $attempts} {
++	    unresolved $test
++	} else {
++	    fail $test
++	}
 +    }
 +
 +    # Exit and detach the process.
@@ -555,18 +618,15 @@
 +
 +corefunc nonthreaded
 +
-+# build the test case first without threads
++# build the test case also with threads
 +#
 +if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DUSE_THREADS}] != "" } {
 +    gdb_suppress_entire_file "Testcase threaded compile failed, so all tests in this file will automatically fail."
 +}
 +
 +corefunc threaded
-+
-+return 0
-diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.c gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.c
---- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.c	2007-06-06 16:36:34.000000000 +0200
-+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.c	2007-06-06 13:33:11.000000000 +0200
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ ./gdb/testsuite/gdb.threads/attach-stopped.c	29 Jun 2007 22:06:06 -0000
 @@ -0,0 +1,51 @@
 +/* This testcase is part of GDB, the GNU debugger.
 +
@@ -619,10 +679,9 @@
 +
 +  return 0;
 +}
-diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.exp gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.exp
---- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.exp	2007-06-06 16:36:34.000000000 +0200
-+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.exp	2007-06-06 13:33:11.000000000 +0200
-@@ -0,0 +1,208 @@
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ ./gdb/testsuite/gdb.threads/attach-stopped.exp	29 Jun 2007 22:06:06 -0000
+@@ -0,0 +1,213 @@
 +# Copyright 2005-2007
 +
 +# This program is free software; you can redistribute it and/or modify
@@ -682,8 +741,10 @@
 +    # that it can be attached to.
 +
 +    set testpid [eval exec $binfile &]
-+    exec sleep 2
-+       
++
++    # Avoid some race:
++    sleep 2
++
 +    # Stop the program 
 +    remote_exec build "kill -s STOP ${testpid}"
 +
@@ -725,6 +786,9 @@
 +       
 +    gdb_exit
 +
++    # Avoid some race:
++    sleep 2
++
 +    set fileid [open /proc/${testpid}/status r];
 +    gets $fileid line1;
 +    gets $fileid line2;
@@ -790,7 +854,7 @@
 +    gdb_exit
 +
 +    # Avoid some race:
-+    exec sleep 2
++    sleep 2
 +
 +    # At this point, the process should be sleeping
 +
@@ -831,3 +895,41 @@
 +corefunc threaded
 +
 +return 0
+--- ./gdb/doc/gdb.texinfo	1 Jul 2007 09:13:05 -0000	1.418
++++ ./gdb/doc/gdb.texinfo	1 Jul 2007 09:55:14 -0000
+@@ -2167,16 +2167,29 @@ can step and continue; you can modify st
+ process continue running, you may use the @code{continue} command after
+ attaching @value{GDBN} to the process.
+ 
++For a process already being stopped before the @code{attach} command executed
++you get the informational message below.  Other signals may be occasionally
++shown if they were being delivered right the time the @code{attach} command
++executed.  Such process is left still stopped after the @code{detach} command
++as long as you have not used the @code{continue} command (or similiar one)
++during your debugging session.
++
++ at smallexample
++Attaching to program: /bin/sleep, process 16289
++Redelivering pending Stopped (signal).
++ at end smallexample
++
+ @table @code
+ @kindex detach
+ @item detach
+ When you have finished debugging the attached process, you can use the
+- at code{detach} command to release it from @value{GDBN} control.  Detaching
+-the process continues its execution.  After the @code{detach} command,
+-that process and @value{GDBN} become completely independent once more, and you
+-are ready to @code{attach} another process or start one with @code{run}.
+- at code{detach} does not repeat if you press @key{RET} again after
+-executing the command.
++ at code{detach} command to release it from @value{GDBN} control.  Detaching the
++process continues its execution unless it was already stopped before the
++attachment and a @code{continue} type command has not been executed.  After the
++ at code{detach} command, that process and @value{GDBN} become completely
++independent once more, and you are ready to @code{attach} another process or
++start one with @code{run}.  @code{detach} does not repeat if you press
++ at key{RET} again after executing the command.
+ @end table
+ 
+ If you exit @value{GDBN} while you have an attached process, you detach


Index: gdb.spec
===================================================================
RCS file: /cvs/pkgs/rpms/gdb/devel/gdb.spec,v
retrieving revision 1.243
retrieving revision 1.244
diff -u -r1.243 -r1.244
--- gdb.spec	28 Aug 2007 14:46:38 -0000	1.243
+++ gdb.spec	16 Sep 2007 22:34:35 -0000	1.244
@@ -11,7 +11,7 @@
 Version: 6.6
 
 # The release always contains a leading reserved number, start it at 1.
-Release: 26%{?dist}
+Release: 27%{?dist}
 
 License: GPL
 Group: Development/Debuggers
@@ -345,7 +345,7 @@
 # Avoid too long timeouts on failing cases of "annota1.exp annota3.exp".
 Patch254: gdb-6.6-testsuite-timeouts.patch
 
-# Fix attaching a stopped nonthreaded/threaded process (BZ 219118, 233852).
+# Fix attaching to stopped processes (BZ 219118, 233852).
 # Fix attaching during a pending signal being delivered.
 Patch256: gdb-6.6-bz233852-attach-signalled.patch
 
@@ -683,6 +683,9 @@
 # don't include the files in include, they are part of binutils
 
 %changelog
+* Sun Sep 16 2007 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.6-27
+- Fix attaching to stopped processes and/or pending signals.
+
 * Tue Aug 28 2007 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.6-26
 - New fast verification whether the .debug file matches its peer (build-id).
 - New locating of the matching binaries from the pure core file (build-id).




More information about the fedora-extras-commits mailing list