siosm / rpms / gdb

Forked from rpms/gdb a year ago
Clone
4e636f8
diff -u -rup gdb-6.6-orig/gdb/inf-ptrace.c gdb-6.6/gdb/inf-ptrace.c
4e636f8
--- gdb-6.6-orig/gdb/inf-ptrace.c	2006-01-24 23:34:34.000000000 +0100
4e636f8
+++ gdb-6.6/gdb/inf-ptrace.c	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -38,6 +38,9 @@
4e636f8
 
4e636f8
 /* HACK: Save the ptrace ops returned by inf_ptrace_target.  */
4e636f8
 static struct target_ops *ptrace_ops_hack;
4e636f8
+
4e636f8
+/* Stored PID of the process being stopped during attach.  */
4e636f8
+static pid_t stopped_pid;
4e636f8
 
4e636f8
 
4e636f8
 #ifdef PT_GET_PROCESS_STATE
4e636f8
@@ -69,14 +72,20 @@ inf_ptrace_follow_fork (struct target_op
4e636f8
 
4e636f8
   if (follow_child)
4e636f8
     {
4e636f8
+      unsigned long sig = 0;
4e636f8
+
4e636f8
       inferior_ptid = pid_to_ptid (fpid);
4e636f8
       detach_breakpoints (pid);
4e636f8
 
4e636f8
       /* Reset breakpoints in the child as appropriate.  */
4e636f8
       follow_inferior_reset_breakpoints ();
4e636f8
 
4e636f8
-      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
4e636f8
-	perror_with_name (("ptrace"));
4e636f8
+      /* Stop the process again if it was stopped during the attachment.  */
4e636f8
+      if (pid == stopped_pid)
4e636f8
+	sig = target_signal_to_host (TARGET_SIGNAL_STOP));
4e636f8
+
4e636f8
+      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, (void *) sig) == -1)
4e636f8
+	perror_with_name (("ptrace PT_DETACH"));
4e636f8
     }
4e636f8
   else
4e636f8
     {
4e636f8
@@ -173,6 +182,21 @@ inf_ptrace_mourn_inferior (void)
4e636f8
   generic_mourn_inferior ();
4e636f8
 }
4e636f8
 
4e636f8
+/* Wrapper function for waitpid which handles EINTR.  */
4e636f8
+
4e636f8
+static int
4e636f8
+my_waitpid (int pid, int *status, int flags)
4e636f8
+{
4e636f8
+  int ret;
4e636f8
+  do
4e636f8
+    {
4e636f8
+      ret = waitpid (pid, status, flags);
4e636f8
+    }
4e636f8
+  while (ret == -1 && errno == EINTR);
4e636f8
+
4e636f8
+  return ret;
4e636f8
+}
4e636f8
+
4e636f8
 /* Attach to the process specified by ARGS.  If FROM_TTY is non-zero,
4e636f8
    be chatty about it.  */
4e636f8
 
4e636f8
@@ -180,8 +204,14 @@ static void
4e636f8
 inf_ptrace_attach (char *args, int from_tty)
4e636f8
 {
4e636f8
   char *exec_file;
4e636f8
-  pid_t pid;
4e636f8
+  pid_t pid, got_pid;
4e636f8
   char *dummy;
4e636f8
+  int status;
4e636f8
+  unsigned long sig;
4e636f8
+  FILE *status_file;
4e636f8
+  char name[40];
4e636f8
+  char buf[100]; 
4e636f8
+  int sigstop = target_signal_to_host (TARGET_SIGNAL_STOP);
4e636f8
 
4e636f8
   if (!args)
4e636f8
     error_no_arg (_("process-id to attach"));
4e636f8
@@ -210,11 +240,64 @@ inf_ptrace_attach (char *args, int from_
4e636f8
     }
4e636f8
 
4e636f8
 #ifdef PT_ATTACH
4e636f8
+  stopped_pid = 0;
4e636f8
+  /* There is a small moment after PTRACE_ATTACH where PTRACE_CONT will
4e636f8
+     succeed only for originally stopped processes.  Unfortunately in a moment
4e636f8
+     PTRACE_ATTACH will deliver its SIGSTOP and PTRACE_CONT shows no difference
4e636f8
+     since that moment.
4e636f8
+     "/proc/%d/status" is also a race but it is safe for unstopped cases.  */
4e636f8
+  sprintf (name, "/proc/%d/status", (int) pid);
4e636f8
+  status_file = fopen (name, "r");
4e636f8
+  if (status_file != NULL)
4e636f8
+    {
4e636f8
+      int have_state = 0;
4e636f8
+
4e636f8
+      while (fgets (buf, 100, status_file))
4e636f8
+	{
4e636f8
+	  if (strncmp (buf, "State:", 6) == 0)
4e636f8
+	    {
4e636f8
+	      have_state = 1;
4e636f8
+	      break;
4e636f8
+	    }
4e636f8
+	} 
4e636f8
+      if (have_state != 0 && strstr (buf, "T (stopped)") != NULL)
4e636f8
+	stopped_pid = pid;
4e636f8
+      fclose (status_file);
4e636f8
+    }
4e636f8
+
4e636f8
   errno = 0;
4e636f8
   ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
4e636f8
   if (errno != 0)
4e636f8
     perror_with_name (("ptrace"));
4e636f8
   attach_flag = 1;
4e636f8
+
4e636f8
+  /* Deliver one SIGSTOP just for sure.
4e636f8
+     If the process was already stopped AND some other process (like shell)
4e636f8
+     has already waited for it we would get stuck in waitpid ().  */
4e636f8
+  sig = sigstop;
4e636f8
+  do
4e636f8
+    {
4e636f8
+      if (sig != sigstop)
4e636f8
+	printf_unfiltered (_("Redelivering pending %s.\n"),
4e636f8
+		       target_signal_to_string (target_signal_from_host (sig)));
4e636f8
+      errno = 0;
4e636f8
+      ptrace (PT_CONTINUE, pid, (PTRACE_TYPE_ARG3)1, (void *) sig);
4e636f8
+      /* For unstopped processes the preventive signal may ESRCH.  */
4e636f8
+      if (errno != 0 && sig != sigstop)
4e636f8
+	perror_with_name ("ptrace PT_CONTINUE");
4e636f8
+
4e636f8
+      got_pid = my_waitpid (pid, &status, 0);
4e636f8
+      gdb_assert (got_pid == pid);
4e636f8
+
4e636f8
+      /* Check if the thread has exited.  */
4e636f8
+      if (WIFEXITED (status) || WIFSIGNALED (status))
4e636f8
+	error (_("Program %s exited.\n"),
4e636f8
+	       target_pid_to_str (pid_to_ptid (pid)));
4e636f8
+      gdb_assert (WIFSTOPPED (status));
4e636f8
+      sig = WSTOPSIG (status);
4e636f8
+      gdb_assert (sig != 0);
4e636f8
+    }
4e636f8
+  while (sig != sigstop);
4e636f8
 #else
4e636f8
   error (_("This system does not support attaching to a process"));
4e636f8
 #endif
4e636f8
@@ -240,14 +323,16 @@ inf_ptrace_post_attach (int pid)
4e636f8
 
4e636f8
 #endif
4e636f8
 
4e636f8
-/* Detach from the inferior, optionally passing it the signal
4e636f8
-   specified by ARGS.  If FROM_TTY is non-zero, be chatty about it.  */
4e636f8
+/* Detach from the inferior.  If FROM_TTY is non-zero, be chatty about it.  */
4e636f8
 
4e636f8
 static void
4e636f8
 inf_ptrace_detach (char *args, int from_tty)
4e636f8
 {
4e636f8
   pid_t pid = ptid_get_pid (inferior_ptid);
4e636f8
-  int sig = 0;
4e636f8
+  unsigned long sig = 0;
4e636f8
+
4e636f8
+  if (args)
4e636f8
+    error (_("Too many arguments"));
4e636f8
 
4e636f8
   if (from_tty)
4e636f8
     {
4e636f8
@@ -258,18 +343,19 @@ inf_ptrace_detach (char *args, int from_
4e636f8
 			 target_pid_to_str (pid_to_ptid (pid)));
4e636f8
       gdb_flush (gdb_stdout);
4e636f8
     }
4e636f8
-  if (args)
4e636f8
-    sig = atoi (args);
4e636f8
 
4e636f8
 #ifdef PT_DETACH
4e636f8
   /* We'd better not have left any breakpoints in the program or it'll
4e636f8
      die when it hits one.  Also note that this may only work if we
4e636f8
      previously attached to the inferior.  It *might* work if we
4e636f8
      started the process ourselves.  */
4e636f8
+  /* Stop the process again if it was stopped during the attachment.  */
4e636f8
+  if (pid == stopped_pid)
4e636f8
+    sig = target_signal_to_host (TARGET_SIGNAL_STOP);
4e636f8
   errno = 0;
4e636f8
-  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
4e636f8
+  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, (void *) sig);
4e636f8
   if (errno != 0)
4e636f8
-    perror_with_name (("ptrace"));
4e636f8
+    perror_with_name (("ptrace PT_DETACH"));
4e636f8
   attach_flag = 0;
4e636f8
 #else
4e636f8
   error (_("This system does not support detaching from a process"));
4e636f8
@@ -324,6 +410,12 @@ inf_ptrace_resume (ptid_t ptid, int step
4e636f8
        single-threaded processes, so simply resume the inferior.  */
4e636f8
     pid = ptid_get_pid (inferior_ptid);
4e636f8
 
4e636f8
+  /* At this point, we are going to resume the inferior and if we
4e636f8
+     have attached to a stopped process, we no longer should leave
4e636f8
+     it as stopped if the user detaches.  */
4e636f8
+  if (!step && pid == stopped_pid)
4e636f8
+    stopped_pid = 0;
4e636f8
+
4e636f8
   if (step)
4e636f8
     {
4e636f8
       /* If this system does not support PT_STEP, a higher level
4e636f8
diff -u -rup gdb-6.6-orig/gdb/linux-nat.c gdb-6.6/gdb/linux-nat.c
4e636f8
--- gdb-6.6-orig/gdb/linux-nat.c	2007-06-06 13:30:52.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/linux-nat.c	2007-06-06 13:57:18.000000000 +0200
4e636f8
@@ -994,6 +994,7 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
4e636f8
     {
4e636f8
       pid_t pid;
4e636f8
       int status;
4e636f8
+      unsigned long sig;
4e636f8
 
4e636f8
       if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
4e636f8
 	{
4e636f8
@@ -1015,32 +1016,54 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver
4e636f8
 			    "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
4e636f8
 			    target_pid_to_str (ptid));
4e636f8
 
4e636f8
-      pid = my_waitpid (GET_LWP (ptid), &status, 0);
4e636f8
-      if (pid == -1 && errno == ECHILD)
4e636f8
+      sig = SIGSTOP;
4e636f8
+      do
4e636f8
 	{
4e636f8
-	  /* Try again with __WCLONE to check cloned processes.  */
4e636f8
-	  pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
4e636f8
+	  if (sig != SIGSTOP)
4e636f8
+	    printf_unfiltered (_("Redelivering pending %s.\n"),
4e636f8
+		       target_signal_to_string (target_signal_from_host (sig)));
4e636f8
+	  /* For unstopped processes the preventive signal may ESRCH.  */
4e636f8
+	  if (ptrace (PTRACE_CONT, GET_LWP (ptid), (PTRACE_TYPE_ARG3)1,
4e636f8
+		      (void *) sig) != 0 && sig != SIGSTOP)
4e636f8
+	    perror_with_name ("ptrace");
4e636f8
+
4e636f8
+	  pid = my_waitpid (GET_LWP (ptid), &status, 0);
4e636f8
 	  if (pid == -1 && errno == ECHILD)
4e636f8
-	    error (_("Can't attach %s (%s) - possible SELinux denial,"
4e636f8
-		     " check your /var/log/messages for `avc: denied'"),
4e636f8
-		   target_pid_to_str (ptid), safe_strerror (errno));
4e636f8
-	  lp->cloned = 1;
4e636f8
-	}
4e636f8
+	    {
4e636f8
+	      /* Try again with __WCLONE to check cloned processes.  */
4e636f8
+	      pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
4e636f8
+	      if (pid == -1 && errno == ECHILD)
4e636f8
+		error (_("Can't attach %s (%s) - possible SELinux denial,"
4e636f8
+			 " check your /var/log/messages for `avc: denied'"),
4e636f8
+		       target_pid_to_str (ptid), safe_strerror (errno));
4e636f8
+	      lp->cloned = 1;
4e636f8
+	    }
4e636f8
+	  gdb_assert (pid == GET_LWP (ptid));
4e636f8
 
4e636f8
-      gdb_assert (pid == GET_LWP (ptid)
4e636f8
-		  && WIFSTOPPED (status) && WSTOPSIG (status));
4e636f8
+	  if (debug_linux_nat)
4e636f8
+	    {
4e636f8
+	      fprintf_unfiltered (gdb_stdlog,
4e636f8
+				  "LLAL: waitpid %s received %s\n",
4e636f8
+				  target_pid_to_str (ptid),
4e636f8
+				  status_to_str (status));
4e636f8
+	    }
4e636f8
+
4e636f8
+	  /* Check if the thread has exited.  */
4e636f8
+	  if (WIFEXITED (status) || WIFSIGNALED (status))
4e636f8
+	    {
4e636f8
+	      warning (_("Thread %s exited: %s"), target_pid_to_str (ptid),
4e636f8
+		       status_to_str (status));
4e636f8
+	      return -1;
4e636f8
+	    }
4e636f8
+	  gdb_assert (WIFSTOPPED (status));
4e636f8
+	  sig = WSTOPSIG (status);
4e636f8
+	  gdb_assert (sig != 0);
4e636f8
+	}
4e636f8
+      while (sig != SIGSTOP);
4e636f8
 
4e636f8
       target_post_attach (pid);
4e636f8
 
4e636f8
       lp->stopped = 1;
4e636f8
-
4e636f8
-      if (debug_linux_nat)
4e636f8
-	{
4e636f8
-	  fprintf_unfiltered (gdb_stdlog,
4e636f8
-			      "LLAL: waitpid %s received %s\n",
4e636f8
-			      target_pid_to_str (ptid),
4e636f8
-			      status_to_str (status));
4e636f8
-	}
4e636f8
     }
4e636f8
   else
4e636f8
     {
4e636f8
@@ -1065,8 +1088,6 @@ static void
4e636f8
 linux_nat_attach (char *args, int from_tty)
4e636f8
 {
4e636f8
   struct lwp_info *lp;
4e636f8
-  pid_t pid;
4e636f8
-  int status;
4e636f8
 
4e636f8
   /* FIXME: We should probably accept a list of process id's, and
4e636f8
      attach all of them.  */
4e636f8
@@ -1076,22 +1097,6 @@ linux_nat_attach (char *args, int from_t
4e636f8
   inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
4e636f8
   lp = add_lwp (inferior_ptid);
4e636f8
 
4e636f8
-  /* Make sure the initial process is stopped.  The user-level threads
4e636f8
-     layer might want to poke around in the inferior, and that won't
4e636f8
-     work if things haven't stabilized yet.  */
4e636f8
-  pid = my_waitpid (GET_PID (inferior_ptid), &status, 0);
4e636f8
-  if (pid == -1 && errno == ECHILD)
4e636f8
-    {
4e636f8
-      warning (_("%s is a cloned process"), target_pid_to_str (inferior_ptid));
4e636f8
-
4e636f8
-      /* Try again with __WCLONE to check cloned processes.  */
4e636f8
-      pid = my_waitpid (GET_PID (inferior_ptid), &status, __WCLONE);
4e636f8
-      lp->cloned = 1;
4e636f8
-    }
4e636f8
-
4e636f8
-  gdb_assert (pid == GET_PID (inferior_ptid)
4e636f8
-	      && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
4e636f8
-
4e636f8
   lp->stopped = 1;
4e636f8
 
4e636f8
   /* Fake the SIGSTOP that core GDB expects.  */
4e636f8
@@ -1099,8 +1104,8 @@ linux_nat_attach (char *args, int from_t
4e636f8
   lp->resumed = 1;
4e636f8
   if (debug_linux_nat)
4e636f8
     {
4e636f8
-      fprintf_unfiltered (gdb_stdlog,
4e636f8
-			  "LLA: waitpid %ld, faking SIGSTOP\n", (long) pid);
4e636f8
+      fprintf_unfiltered (gdb_stdlog, "LLA: waitpid %d, faking SIGSTOP\n",
4e636f8
+			  GET_PID (inferior_ptid));
4e636f8
     }
4e636f8
 }
4e636f8
 
4e636f8
diff -u -rup gdb-6.6-orig/gdb/target.h gdb-6.6/gdb/target.h
4e636f8
--- gdb-6.6-orig/gdb/target.h	2007-06-06 13:30:52.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/target.h	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -529,9 +529,9 @@ void target_close (struct target_ops *ta
4e636f8
    to the `attach' command by the user.  This routine can be called
4e636f8
    when the target is not on the target-stack, if the target_can_run
4e636f8
    routine returns 1; in that case, it must push itself onto the stack.
4e636f8
-   Upon exit, the target should be ready for normal operations, and
4e636f8
-   should be ready to deliver the status of the process immediately
4e636f8
-   (without waiting) to an upcoming target_wait call.  */
4e636f8
+   Upon exit, the target should be ready for normal operations.
4e636f8
+   The status of the inferior is already processed and possibly pending
4e636f8
+   signals redelivered.  */
4e636f8
 
4e636f8
 #define	target_attach(args, from_tty)	\
4e636f8
      (*current_target.to_attach) (args, from_tty)
4e636f8
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
4e636f8
--- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.c	2007-06-06 16:36:34.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.c	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -0,0 +1,65 @@
4e636f8
+/* This testcase is part of GDB, the GNU debugger.
4e636f8
+
4e636f8
+   Copyright 2007 Free Software Foundation, Inc.
4e636f8
+
4e636f8
+   This program is free software; you can redistribute it and/or modify
4e636f8
+   it under the terms of the GNU General Public License as published by
4e636f8
+   the Free Software Foundation; either version 2 of the License, or
4e636f8
+   (at your option) any later version.
4e636f8
+
4e636f8
+   This program is distributed in the hope that it will be useful,
4e636f8
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
4e636f8
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4e636f8
+   GNU General Public License for more details.
4e636f8
+ 
4e636f8
+   You should have received a copy of the GNU General Public License
4e636f8
+   along with this program; if not, write to the Free Software
4e636f8
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4e636f8
+
4e636f8
+#include <signal.h>
4e636f8
+#include <unistd.h>
4e636f8
+#include <string.h>
4e636f8
+#include <stdio.h>
4e636f8
+#include <stdlib.h>
4e636f8
+#ifdef USE_THREADS
4e636f8
+#include <pthread.h>
4e636f8
+#endif
4e636f8
+
4e636f8
+void action(int sig, siginfo_t * info, void *uc)
4e636f8
+{
4e636f8
+  raise (SIGALRM);
4e636f8
+}
4e636f8
+
4e636f8
+static void *func (void *arg)
4e636f8
+{
4e636f8
+  struct sigaction act;
4e636f8
+
4e636f8
+  memset (&act, 0, sizeof(struct sigaction));
4e636f8
+  act.sa_sigaction = action;
4e636f8
+  act.sa_flags = SA_RESTART;
4e636f8
+  sigaction (SIGALRM, &act, 0);
4e636f8
+
4e636f8
+  raise (SIGALRM);
4e636f8
+
4e636f8
+  abort ();
4e636f8
+  /* NOTREACHED */
4e636f8
+  return NULL;
4e636f8
+}
4e636f8
+
4e636f8
+int main ()
4e636f8
+{
4e636f8
+
4e636f8
+#ifndef USE_THREADS
4e636f8
+
4e636f8
+  func (NULL);
4e636f8
+
4e636f8
+#else
4e636f8
+
4e636f8
+  pthread_t th;
4e636f8
+  pthread_create (&th, NULL, func, NULL);
4e636f8
+  pthread_join (th, NULL);
4e636f8
+
4e636f8
+#endif
4e636f8
+
4e636f8
+  return 0;
4e636f8
+}
4e636f8
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
4e636f8
--- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-into-signal.exp	2007-06-06 16:36:34.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-into-signal.exp	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -0,0 +1,153 @@
4e636f8
+# Copyright 2007
4e636f8
+
4e636f8
+# This program is free software; you can redistribute it and/or modify
4e636f8
+# it under the terms of the GNU General Public License as published by
4e636f8
+# the Free Software Foundation; either version 2 of the License, or
4e636f8
+# (at your option) any later version.
4e636f8
+# 
4e636f8
+# This program is distributed in the hope that it will be useful,
4e636f8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4e636f8
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4e636f8
+# GNU General Public License for more details.
4e636f8
+# 
4e636f8
+# You should have received a copy of the GNU General Public License
4e636f8
+# along with this program; if not, write to the Free Software
4e636f8
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4e636f8
+
4e636f8
+# This test was created by modifying attach-stopped.exp.
4e636f8
+# This file was created by Jan Kratochvil <jan.kratochvil@redhat.com>.
4e636f8
+
4e636f8
+if $tracelevel then {
4e636f8
+    strace $tracelevel
4e636f8
+}
4e636f8
+
4e636f8
+set prms_id 0
4e636f8
+set bug_id 0
4e636f8
+
4e636f8
+set testfile "attach-into-signal"
4e636f8
+set srcfile  ${testfile}.c
4e636f8
+set binfile  ${objdir}/${subdir}/${testfile}
4e636f8
+set escapedbinfile  [string_to_regexp ${objdir}/${subdir}/${testfile}]
4e636f8
+
4e636f8
+remote_exec build "rm -f ${binfile}"
4e636f8
+# For debugging this test
4e636f8
+#
4e636f8
+#log_user 1
4e636f8
+
4e636f8
+proc corefunc { threadtype } {
4e636f8
+    global srcfile
4e636f8
+    global binfile
4e636f8
+    global escapedbinfile
4e636f8
+    global srcdir
4e636f8
+    global subdir
4e636f8
+    global gdb_prompt
4e636f8
+
4e636f8
+    if [get_compiler_info ${binfile}] {
4e636f8
+	return -1
4e636f8
+    }
4e636f8
+
4e636f8
+    # Start the program running and then wait for a bit, to be sure
4e636f8
+    # that it can be attached to.
4e636f8
+    # Statistically there is a better chance without giving process a nice.
4e636f8
+
4e636f8
+    set testpid [eval exec $binfile &]
4e636f8
+    exec sleep 2
4e636f8
+
4e636f8
+    # Run 2 passes of the test.
4e636f8
+    # The C file inferior stops pending its signals if a single one is lost,
4e636f8
+    # we test successful redelivery of the caught signal by the 2nd pass.
4e636f8
+
4e636f8
+    # linux-2.6.20.4.x86_64 had maximal attempt # 20 in 4 test runs.
4e636f8
+    set attempts 100
4e636f8
+    set attempt 0
4e636f8
+    set passes 1
4e636f8
+    while { $passes < 3 && $attempt < $attempts } {
4e636f8
+
4e636f8
+	# Start with clean gdb
4e636f8
+	gdb_exit
4e636f8
+	gdb_start
4e636f8
+	gdb_reinitialize_dir $srcdir/$subdir
4e636f8
+	gdb_load ${binfile}
4e636f8
+
4e636f8
+	# No PASS message as we may be looping in multiple attempts.
4e636f8
+	gdb_test "set debug lin-lwp 1" "" ""
4e636f8
+
4e636f8
+	set test "$threadtype: set file (pass $passes), before attach1 to stopped process"
4e636f8
+	if {[gdb_test_multiple "file $binfile" $test {
4e636f8
+	   -re "Load new symbol table from.*y or n. $" {
4e636f8
+		# No PASS message as we may be looping in multiple attempts.
4e636f8
+		gdb_test "y" "Reading symbols from $escapedbinfile\.\.\.*done." ""
4e636f8
+	    }
4e636f8
+	    -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $" {
4e636f8
+		# No PASS message as we may be looping in multiple attempts.
4e636f8
+	    }
4e636f8
+	}] != 0 } {
4e636f8
+	    break
4e636f8
+	}
4e636f8
+
4e636f8
+	# Main test:
4e636f8
+	set test "$threadtype: attach (pass $passes), pending signal catch"
4e636f8
+	if {[gdb_test_multiple "attach $testpid" $test {
4e636f8
+	    -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*Redelivering pending Alarm clock..*$gdb_prompt $" {
4e636f8
+		# nonthreaded:
4e636f8
+		pass $test
4e636f8
+		verbose -log "$test succeeded on the attempt # $attempt of $attempts"
4e636f8
+		set passes [expr $passes + 1]
4e636f8
+	    }
4e636f8
+	    -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
4e636f8
+		# nonthreaded:
4e636f8
+		# We just lack the luck, we should try it again.
4e636f8
+		set attempt [expr $attempt + 1]
4e636f8
+	    }
4e636f8
+	    -re "Attaching to process $testpid.*Redelivering pending Alarm clock..*$gdb_prompt $" {
4e636f8
+		# threaded:
4e636f8
+		pass $test
4e636f8
+		verbose -log "$test succeeded on the attempt # $attempt of $attempts"
4e636f8
+		set passes [expr $passes + 1]
4e636f8
+	    }
4e636f8
+	    -re "Attaching to process $testpid.*$gdb_prompt $" {
4e636f8
+		# threaded:
4e636f8
+		# We just lack the luck, we should try it again.
4e636f8
+		set attempt [expr $attempt - 1]
4e636f8
+	    }
4e636f8
+	}] != 0 } {
4e636f8
+	    break
4e636f8
+	}
4e636f8
+    }
4e636f8
+    if {$passes < 3} {
4e636f8
+	fail $test
4e636f8
+    }
4e636f8
+
4e636f8
+    # Exit and detach the process.
4e636f8
+       
4e636f8
+    gdb_exit
4e636f8
+
4e636f8
+    # Make sure we don't leave a process around to confuse
4e636f8
+    # the next test run (and prevent the compile by keeping
4e636f8
+    # the text file busy), in case the "set should_exit" didn't
4e636f8
+    # work.
4e636f8
+
4e636f8
+    # Continue the program - some Linux kernels need it before -9 if the
4e636f8
+    # process is stopped.
4e636f8
+    remote_exec build "kill -s CONT ${testpid}"
4e636f8
+       
4e636f8
+    remote_exec build "kill -9 ${testpid}"
4e636f8
+}
4e636f8
+
4e636f8
+# build the test case first without threads
4e636f8
+#
4e636f8
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
4e636f8
+    gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
4e636f8
+}
4e636f8
+
4e636f8
+corefunc nonthreaded
4e636f8
+
4e636f8
+# build the test case first without threads
4e636f8
+#
4e636f8
+if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DUSE_THREADS}] != "" } {
4e636f8
+    gdb_suppress_entire_file "Testcase threaded compile failed, so all tests in this file will automatically fail."
4e636f8
+}
4e636f8
+
4e636f8
+corefunc threaded
4e636f8
+
4e636f8
+return 0
4e636f8
diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.c gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.c
4e636f8
--- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.c	2007-06-06 16:36:34.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.c	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -0,0 +1,51 @@
4e636f8
+/* This testcase is part of GDB, the GNU debugger.
4e636f8
+
4e636f8
+   Copyright 2005-2007 Free Software Foundation, Inc.
4e636f8
+
4e636f8
+   This program is free software; you can redistribute it and/or modify
4e636f8
+   it under the terms of the GNU General Public License as published by
4e636f8
+   the Free Software Foundation; either version 2 of the License, or
4e636f8
+   (at your option) any later version.
4e636f8
+
4e636f8
+   This program is distributed in the hope that it will be useful,
4e636f8
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
4e636f8
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4e636f8
+   GNU General Public License for more details.
4e636f8
+ 
4e636f8
+   You should have received a copy of the GNU General Public License
4e636f8
+   along with this program; if not, write to the Free Software
4e636f8
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4e636f8
+
4e636f8
+/* This program is intended to be started outside of gdb, then
4e636f8
+   manually stopped via a signal.  */
4e636f8
+
4e636f8
+#include <stddef.h>
4e636f8
+#include <unistd.h>
4e636f8
+#ifdef USE_THREADS
4e636f8
+#include <pthread.h>
4e636f8
+#endif
4e636f8
+
4e636f8
+static void *func (void *arg)
4e636f8
+{
4e636f8
+  sleep (10000);  /* Ridiculous time, but we will eventually kill it.  */
4e636f8
+  sleep (10000);  /* Second sleep.  */
4e636f8
+  return NULL;
4e636f8
+}
4e636f8
+
4e636f8
+int main ()
4e636f8
+{
4e636f8
+
4e636f8
+#ifndef USE_THREADS
4e636f8
+
4e636f8
+  func (NULL);
4e636f8
+
4e636f8
+#else
4e636f8
+
4e636f8
+  pthread_t th;
4e636f8
+  pthread_create (&th, NULL, func, NULL);
4e636f8
+  pthread_join (th, NULL);
4e636f8
+
4e636f8
+#endif
4e636f8
+
4e636f8
+  return 0;
4e636f8
+}
4e636f8
diff -u -rup gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.exp gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.exp
4e636f8
--- gdb-6.6-orig/gdb/testsuite/gdb.threads/attach-stopped.exp	2007-06-06 16:36:34.000000000 +0200
4e636f8
+++ gdb-6.6/gdb/testsuite/gdb.threads/attach-stopped.exp	2007-06-06 13:33:11.000000000 +0200
4e636f8
@@ -0,0 +1,208 @@
4e636f8
+# Copyright 2005-2007
4e636f8
+
4e636f8
+# This program is free software; you can redistribute it and/or modify
4e636f8
+# it under the terms of the GNU General Public License as published by
4e636f8
+# the Free Software Foundation; either version 2 of the License, or
4e636f8
+# (at your option) any later version.
4e636f8
+# 
4e636f8
+# This program is distributed in the hope that it will be useful,
4e636f8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4e636f8
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4e636f8
+# GNU General Public License for more details.
4e636f8
+# 
4e636f8
+# You should have received a copy of the GNU General Public License
4e636f8
+# along with this program; if not, write to the Free Software
4e636f8
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4e636f8
+
4e636f8
+# This test was created by modifying attach.exp.
4e636f8
+# This file was created by Jeff Johnston <jjohnstn@redhat.com>.
4e636f8
+# This file was updated by Jan Kratochvil <jan.kratochvil@redhat.com>.
4e636f8
+
4e636f8
+if $tracelevel then {
4e636f8
+    strace $tracelevel
4e636f8
+}
4e636f8
+
4e636f8
+set prms_id 0
4e636f8
+set bug_id 0
4e636f8
+
4e636f8
+# This test only works on Linux
4e636f8
+if { ![istarget "*-*-linux-gnu*"] } {
4e636f8
+    return 0
4e636f8
+}
4e636f8
+
4e636f8
+set testfile "attach-stopped"
4e636f8
+set srcfile  ${testfile}.c
4e636f8
+set binfile  ${objdir}/${subdir}/${testfile}
4e636f8
+set escapedbinfile  [string_to_regexp ${objdir}/${subdir}/${testfile}]
4e636f8
+
4e636f8
+#execute_anywhere "rm -f ${binfile}"
4e636f8
+remote_exec build "rm -f ${binfile}"
4e636f8
+# For debugging this test
4e636f8
+#
4e636f8
+#log_user 1
4e636f8
+
4e636f8
+proc corefunc { threadtype } {
4e636f8
+    global srcfile
4e636f8
+    global binfile
4e636f8
+    global escapedbinfile
4e636f8
+    global srcdir
4e636f8
+    global subdir
4e636f8
+    global gdb_prompt
4e636f8
+
4e636f8
+    if [get_compiler_info ${binfile}] {
4e636f8
+	return -1
4e636f8
+    }
4e636f8
+
4e636f8
+    # Start the program running and then wait for a bit, to be sure
4e636f8
+    # that it can be attached to.
4e636f8
+
4e636f8
+    set testpid [eval exec $binfile &]
4e636f8
+    exec sleep 2
4e636f8
+       
4e636f8
+    # Stop the program 
4e636f8
+    remote_exec build "kill -s STOP ${testpid}"
4e636f8
+
4e636f8
+    # Start with clean gdb
4e636f8
+    gdb_exit
4e636f8
+    gdb_start
4e636f8
+    gdb_reinitialize_dir $srcdir/$subdir
4e636f8
+    gdb_load ${binfile}
4e636f8
+
4e636f8
+    # Verify that we can attach to the process by first giving its
4e636f8
+    # executable name via the file command, and using attach with the
4e636f8
+    # process ID.
4e636f8
+
4e636f8
+    set test "$threadtype: set file, before attach1 to stopped process"
4e636f8
+    gdb_test_multiple "file $binfile" "$test" {
4e636f8
+       -re "Load new symbol table from.*y or n. $" {
4e636f8
+	    gdb_test "y" "Reading symbols from $escapedbinfile\.\.\.*done." \
4e636f8
+		    "$test (re-read)"
4e636f8
+	}
4e636f8
+	-re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $" {
4e636f8
+	    pass "$test"
4e636f8
+	}
4e636f8
+    }
4e636f8
+
4e636f8
+    set test "$threadtype: attach1 to stopped, after setting file"
4e636f8
+    gdb_test_multiple "attach $testpid" "$test" {
4e636f8
+	-re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
4e636f8
+	    pass "$test"
4e636f8
+	}
4e636f8
+    }
4e636f8
+
4e636f8
+    if {[string equal $threadtype threaded]} {
4e636f8
+	gdb_test "thread apply all bt" ".*sleep.*clone.*" "$threadtype: attach1 to stopped bt"
4e636f8
+    } else {
4e636f8
+	gdb_test "bt" ".*sleep.*main.*" "$threadtype: attach1 to stopped bt"
4e636f8
+    }
4e636f8
+
4e636f8
+    # Exit and detach the process.
4e636f8
+       
4e636f8
+    gdb_exit
4e636f8
+
4e636f8
+    set fileid [open /proc/${testpid}/status r];
4e636f8
+    gets $fileid line1;
4e636f8
+    gets $fileid line2;
4e636f8
+    close $fileid;
4e636f8
+
4e636f8
+    set test "$threadtype: attach1, exit leaves process stopped"
4e636f8
+    if {[string match "*(stopped)*" $line2]} {
4e636f8
+      pass $test
4e636f8
+    } else {
4e636f8
+      fail $test
4e636f8
+    }
4e636f8
+
4e636f8
+    # At this point, the process should still be stopped
4e636f8
+
4e636f8
+    gdb_start
4e636f8
+    gdb_reinitialize_dir $srcdir/$subdir
4e636f8
+    gdb_load ${binfile}
4e636f8
+
4e636f8
+    # Verify that we can attach to the process just by giving the
4e636f8
+    # process ID.
4e636f8
+       
4e636f8
+    set test "$threadtype: attach2 to stopped, after setting file"
4e636f8
+    gdb_test_multiple "attach $testpid" "$test" {
4e636f8
+	-re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
4e636f8
+	    pass "$test"
4e636f8
+	}
4e636f8
+    }
4e636f8
+
4e636f8
+    if {[string equal $threadtype threaded]} {
4e636f8
+	gdb_test "thread apply all bt" ".*sleep.*clone.*" "$threadtype: attach2 to stopped bt"
4e636f8
+    } else {
4e636f8
+	gdb_test "bt" ".*sleep.*main.*" "$threadtype: attach2 to stopped bt"
4e636f8
+    }
4e636f8
+    gdb_breakpoint [gdb_get_line_number "$threadtype: Second sleep"]
4e636f8
+    set test "$threadtype: attach2 continue"
4e636f8
+    send_gdb "continue\n"
4e636f8
+    gdb_expect {
4e636f8
+      -re "Continuing"
4e636f8
+	{ pass "continue ($test)" }
4e636f8
+      timeout
4e636f8
+	{ fail "continue ($test) (timeout)" }
4e636f8
+    }
4e636f8
+
4e636f8
+    # For this to work we must be sure to consume the "Continuing."
4e636f8
+    # message first, or GDB's signal handler may not be in place.
4e636f8
+    after 1000 {send_gdb "\003"}
4e636f8
+    set test "$threadtype: attach2 stop interrupt"
4e636f8
+    gdb_expect 10 {
4e636f8
+      -re "Program received signal SIGINT.*$gdb_prompt $"
4e636f8
+	{
4e636f8
+	  pass $test
4e636f8
+	}
4e636f8
+      -re "Breakpoint \[0-9\].*$srcfile.*$gdb_prompt $"
4e636f8
+	{
4e636f8
+	  pass $test
4e636f8
+	}
4e636f8
+      timeout
4e636f8
+	{
4e636f8
+	  fail $test
4e636f8
+	}
4e636f8
+    }
4e636f8
+
4e636f8
+    gdb_exit
4e636f8
+
4e636f8
+    # Avoid some race:
4e636f8
+    exec sleep 2
4e636f8
+
4e636f8
+    # At this point, the process should be sleeping
4e636f8
+
4e636f8
+    set fileid2 [open /proc/${testpid}/status r];
4e636f8
+    gets $fileid2 line1;
4e636f8
+    gets $fileid2 line2;
4e636f8
+    close $fileid2;
4e636f8
+
4e636f8
+    set test "$threadtype: attach2, exit leaves process sleeping"
4e636f8
+    if {[string match "*(sleeping)*" $line2]} {
4e636f8
+      pass $test
4e636f8
+    } else {
4e636f8
+      fail $test
4e636f8
+    }
4e636f8
+
4e636f8
+    # Make sure we don't leave a process around to confuse
4e636f8
+    # the next test run (and prevent the compile by keeping
4e636f8
+    # the text file busy), in case the "set should_exit" didn't
4e636f8
+    # work.
4e636f8
+       
4e636f8
+    remote_exec build "kill -9 ${testpid}"
4e636f8
+}
4e636f8
+
4e636f8
+# build the test case first without threads
4e636f8
+#
4e636f8
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
4e636f8
+    gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
4e636f8
+}
4e636f8
+
4e636f8
+corefunc nonthreaded
4e636f8
+
4e636f8
+# build the test case first without threads
4e636f8
+#
4e636f8
+if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DUSE_THREADS}] != "" } {
4e636f8
+    gdb_suppress_entire_file "Testcase threaded compile failed, so all tests in this file will automatically fail."
4e636f8
+}
4e636f8
+
4e636f8
+corefunc threaded
4e636f8
+
4e636f8
+return 0