fixes
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sat, 25 Dec 2010 00:21:59 +0000 (01:21 +0100)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Sat, 25 Dec 2010 00:21:59 +0000 (01:21 +0100)
src/staptrace.c
src/staptrace.stp

index 2f6f328..5dd7485 100644 (file)
@@ -5,6 +5,7 @@
 #include <libintl.h>
 #include <stdio.h>
 #include <string.h>
+#include <signal.h>
 
 #ifndef STAP_SCRIPT_FILENAME
 #error "STAP_SCRIPT_FILENAME is required"
@@ -51,8 +52,8 @@ dump_args (char **args)
   for (argp = args; *argp; argp++)
     {
       if (argp > args)
-       fputs (", ", stderr);
-      fprintf (stderr, "'%s'", *argp);
+       fputc (' ', stderr);
+      fputs (*argp, stderr);
     }
   fputc ('\n', stderr);
 }
@@ -62,9 +63,9 @@ main (int argc, char **argv)
 {
   char **args, **argp;
 
-  args = xmalloc (sizeof (*args) * argc * 2);
+  args = xmalloc (sizeof (*args) * argc * 2 + 32);
   argp = args;
-  *argp++ = argv[0];
+  *argp++ = "stap";
 
   for (;;)
     {
@@ -114,39 +115,40 @@ main (int argc, char **argv)
 
   if (optind < argc)
     {
-      size_t len;
+      pid_t child;
       int i;
-      char *d;
-      const char *s;
+      static char kill_s[64];
+      static char opt_s[64];
 
-      *argp++ = "-c";
-
-      len = 32;
-      for (i = optind; i < argc; i++)
-       len += 3 + strlen (argv[i]) * 4;
-
-      d = *argp++ = xmalloc (len);
-      d = stpcpy (d, "(exec");
-      for (i = optind; i < argc; i++)
+      child = fork ();
+      switch (child)
        {
-         *d++ = ' ';
-         *d++ = '\'';
-         for (s = argv[optind]; *s; s++)
-           switch (*s)
-             {
-             case '\'':
-               d = stpcpy (d, "'\\''");
-               break;
-             case '\\':
-               *d++ = '\\';
-               /* FALLTHRU */
-             default:
-               *d++ = *s;
-             }
-         *d++ = '\'';
+       case -1:
+         error (EXIT_FAILURE, errno, _("Error calling fork"));
+       case 0:
+         i = raise (SIGSTOP);
+         if (i != 0)
+           error (EXIT_FAILURE, errno, _("Error calling raise (SIGSTOP)"));
+
+         execvp (argv[optind], &argv[optind]);
+         error (EXIT_FAILURE, errno, "Error executing child command");
+       default:
+         break;
        }
-      *d++ = ')';
-      *d++ = 0;
+
+      /* FIXME: Call `kill -CONT' from the systamtap script.  How?  */
+      i = sprintf (kill_s, "kill -CONT %lu; "
+                          "while [ -e /proc/%lu/root ]; do sleep 0.1; done",
+                  (unsigned long) child, (unsigned long) child);
+      if (i <= 0)
+         error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+      *argp++ = "-c";
+      *argp++ = kill_s;
+      i = sprintf (opt_s, "opt_child=%lu", (unsigned long) child);
+      if (i <= 0)
+         error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+      *argp++ = "-G";
+      *argp++ = opt_s;
     }
   *argp++ = opt_Z;
   *argp = NULL;
index 4b61712..24e7775 100755 (executable)
@@ -18,6 +18,8 @@
 # ` = 0' is there to prevent: WARNING: never-assigned global variable
 global opt_f = 0
 global opt_q = 0
+# Override target().
+global opt_child = 0
 
 /* systemtap bug?  /usr/share/doc/systemtap-1.3/SystemTap_Beginners_Guide.pdf
    Example 3.19 reads or writes?  */
@@ -26,11 +28,12 @@ global trace
 global last_tid
 probe begin
 {
-  trace[target ()] = 1
-  last_tid = target ()
+  tid = opt_child > 0 ? opt_child : target ()
+  trace[tid] = 1
+  last_tid = tid
 }
 
-function heading:string ()
+function heading:string (tid:long)
 {
   foreach (tidi in trace limit 2)
     tid_count++
@@ -38,27 +41,23 @@ function heading:string ()
   if (tid_count > 1)
     {
       /* strace really calls TID a "pid".  */
-      return sprintf ("[pid %5d] ", tid ())
+      return sprintf ("[pid %5d] ", tid)
     }
   else
     return ""
 }
 
-global namea
+global funcname
+global nest
 
-function destroy (tid:long)
-{
-  delete namea[tid]
-}
-
-function lhs:string (tid:long)
-{
-  return namea[tid]
-}
 probe end
 {
-  foreach (tid in namea)
-    printf ("%s = ? <tracer terminated>\n", lhs (tid))
+  if (nest[last_tid])
+    printf (") = ? <tracer terminated>\n")
+  foreach (tid in nest)
+    if (tid != last_tid)
+      printf ("%s<... %s resumed> ) = ? <tracer terminated>\n", heading (tid),
+             funcname[tid] != "" ? funcname[tid] : "?");
 }
 
 /* BUG: sleeping function called from invalid context at kernel/mutex.c:94
@@ -72,9 +71,15 @@ function unlock ()
   mutex_unlock (&tracer_mutex);
 %}
 */
-global dummy
-function lock () { dummy = 1; }
-function unlock () { dummy = 1; }
+global lockvar
+function lock ()
+{
+  lockvar++
+}
+function unlock ()
+{
+  lockvar++
+}
 
 #probe kprocess.start
 #{
@@ -104,22 +109,13 @@ probe kprocess.release
   tid = task_tid (task)
   if (trace[tid] != 0)
     {
-      if (namea[tid] != "")
-       {
-         printf ("%s = ?\n", lhs (tid))
-         destroy (tid)
-       }
-# FIXME
-      else if (0)
+      if (nest[tid])
        {
-         /* systemtap bug?  exit_group(2) systemtap calls "exit" and _exit(2)
-            is not caught at all.  */
-         lock ()
-         if (last_tid != tid () && namea[last_tid] != "")
-           printf (" <unfinished ...>\n")
-         last_tid = tid
-         printf ("%s_exit(?) = ?\n", heading ())
-         unlock ()
+         /* FIXME: Do not assume "exit" for the nested calls.  */
+         printf ("%s<... %s resumed> = ?\n", heading (tid),
+                 funcname[tid] != "" ? funcname[tid] : "exit")
+         delete nest[tid]
+         delete funcname[tid]
        }
       delete trace[tid]
       if (!opt_q)
@@ -132,11 +128,12 @@ probe syscall.*
     {
       lock ()
       /* Why is mmap() called recursively twice?  */
-      if (namea[last_tid] != "")
+      if (nest[last_tid])
        printf (" <unfinished ...>\n")
       last_tid = tid ();
-      namea[tid ()] = name
-      printf ("%s%s(%s", heading (), name, argstr)
+      funcname[tid ()] = name
+      nest[tid ()]++
+      printf ("%s%s(%s", heading (tid ()), name, argstr)
       unlock ()
     }
 }
@@ -145,14 +142,15 @@ probe syscall.*.return
   if (trace[tid ()] != 0)
     {
       lock ()
-      if (last_tid != tid () && namea[last_tid] != "")
+      if (last_tid != tid () && nest[last_tid])
        printf (" <unfinished ...>\n")
-      if ((last_tid != tid () && namea[last_tid] != "")
-          || (last_tid == tid () && namea[last_tid] == ""))
-       printf ("%s<... %s resumed> ", heading (), name);
+      if (last_tid != tid () || (last_tid == tid () && !nest[last_tid]))
+       printf ("%s<... %s resumed> ", heading (tid ()), name);
       last_tid = tid ();
       printf (") = %s\n", retstr)
-      destroy (tid ())
+      if (!--nest[tid ()])
+       delete nest[tid ()]
+      delete funcname[tid ()]
       unlock ()
     }
 }