On Mon, 09 Jun 2008 19:23:09 +0200, Matthew Legendre wrote:
>
> We're seeing issues when trying to attached to an already stopped process 
> on recent utrace kernels (seen on Fedora Core 8 and 9)--waitpid reports  
> the arrival of numerous signal 0s,

Being tracked as `stop-attach-then-wait' at:
http://sourceware.org/systemtap/wiki/utrace/tests

While you are right the ptrace-on-utrace emulation is currently incompatible
to ptrace for proper behavior during later ptrace operations you should resume
the job control stop first [attached].  It is a code from a GDB code at:
        http://sourceware.org/ml/gdb-patches/2008-05/msg00022.html


Thanks,
Jan
--- test_attached_to_stopped.c  2008-06-10 23:36:54.000000000 +0200
+++ test_attached_to_stopped-jk.c       2008-06-11 19:19:08.000000000 +0200
@@ -19,6 +19,38 @@ void stop_self()
    kill(getpid(), SIGSTOP);
 }
 
+/* gdb/linux-nat.c  */
+/* Detect `T (stopped)' in `/proc/PID/status'.
+   Other states including `T (tracing stop)' are reported as false.  */
+
+static int
+pid_is_stopped (pid_t pid)
+{
+  FILE *status_file;
+  char buf[100];
+  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, sizeof (buf), status_file))
+       {
+         if (strncmp (buf, "State:", 6) == 0)
+           {
+             have_state = 1;
+             break;
+           }
+       }
+      if (have_state && strstr (buf, "T (stopped)") != NULL)
+       retval = 1;
+      fclose (status_file);
+    }
+  return retval;
+}
+
 int attach_then_run(void (*func)(void))
 {
    int pid, result;
@@ -32,6 +64,28 @@ int attach_then_run(void (*func)(void))
         perror("Ptrace attach error");
         exit(-1);
       }
+      if (pid_is_stopped(pid)) {
+       /* gdb/linux-nat.c  */
+
+       /* The process is definitely stopped.  It is in a job control
+          stop, unless the kernel predates the TASK_STOPPED /
+          TASK_TRACED distinction, in which case it might be in a
+          ptrace stop.  Make sure it is in a ptrace stop; from there we
+          can kill it, signal it, et cetera.
+
+          First make sure there is a pending SIGSTOP.  Since we are
+          already attached, the process can not transition from stopped
+          to running without a PTRACE_CONT; so we know this signal will
+          go into the queue.  The SIGSTOP generated by PTRACE_ATTACH is
+          probably already in the queue (unless this kernel is old
+          enough to use TASK_STOPPED for ptrace stops); but since SIGSTOP
+          is not an RT signal, it can only be queued once.  */
+       kill (pid, SIGSTOP);    /* tgkill() is required for threads!  */
+
+       /* Finally, resume the stopped process.  This will deliver the SIGSTOP
+          (or a higher priority signal, just like normal PTRACE_ATTACH).  */
+       ptrace (PTRACE_CONT, pid, 0, 0);
+      }
       return pid;
    }
 

Reply via email to