[pypy-commit] pypy default: "PYPYLOG=...:filename": add support for "$$" in the filename. If found,

arigo noreply at buildbot.pypy.org
Sun Nov 15 11:41:58 EST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r80689:7cee4e7b7efd
Date: 2015-11-15 17:42 +0100
http://bitbucket.org/pypy/pypy/changeset/7cee4e7b7efd/

Log:	"PYPYLOG=...:filename": add support for "$$" in the filename. If
	found, it is replaced with the current pid. See docs in
	debug_print.h.

diff --git a/rpython/translator/c/src/debug_print.c b/rpython/translator/c/src/debug_print.c
--- a/rpython/translator/c/src/debug_print.c
+++ b/rpython/translator/c/src/debug_print.c
@@ -23,13 +23,14 @@
 static char *debug_start_colors_2 = "";
 static char *debug_stop_colors = "";
 static char *debug_prefix = NULL;
-static char *debug_filename = NULL;
-static char *debug_filename_with_fork = NULL;
 
-static void _pypy_debug_open(char *filename)
+static void pypy_debug_open(void)
 {
+  char *filename = getenv("PYPYLOG");
+
   if (filename && filename[0])
     {
+      char *newfilename = NULL, *doubledollar;
       char *colon = strchr(filename, ':');
       if (filename[0] == '+')
         {
@@ -51,11 +52,38 @@
           debug_prefix[n] = '\0';
           filename = colon + 1;
         }
+      doubledollar = strstr(filename, "$$");
+      if (doubledollar)  /* a "$$" in the filename is replaced with the pid */
+        {
+          newfilename = malloc(strlen(filename) + 32);
+          if (newfilename != NULL)
+            {
+              char *p = newfilename;
+              memcpy(p, filename, doubledollar - filename);
+              p += doubledollar - filename;
+              sprintf(p, "%ld", (long)getpid());
+              strcat(p, doubledollar + 2);
+              filename = newfilename;
+            }
+        }
       if (strcmp(filename, "-") != 0)
         {
-          debug_filename = strdup(filename);
           pypy_debug_file = fopen(filename, "w");
         }
+
+      if (doubledollar)
+        {
+          free(newfilename);   /* if not null */
+          /* the env var is kept and passed to subprocesses */
+        }
+      else
+        {
+#ifndef _WIN32
+          unsetenv("PYPYLOG");
+#else
+          putenv("PYPYLOG=");
+#endif
+        }
     }
   if (!pypy_debug_file)
     {
@@ -67,20 +95,9 @@
           debug_stop_colors = "\033[0m";
         }
     }
-  if (filename)
-#ifndef _WIN32
-    unsetenv("PYPYLOG");   /* don't pass it to subprocesses */
-#else
-    putenv("PYPYLOG=");    /* don't pass it to subprocesses */
-#endif
   debug_ready = 1;
 }
 
-static void pypy_debug_open(void)
-{
-    _pypy_debug_open(getenv("PYPYLOG"));
-}
-
 long pypy_debug_offset(void)
 {
   if (!debug_ready)
@@ -99,21 +116,19 @@
 
 void pypy_debug_forked(long original_offset)
 {
-  if (debug_filename != NULL)
+  /* 'original_offset' ignored.  It used to be that the forked log
+     files started with this offset printed out, so that we can
+     rebuild the tree structure.  That's overkill... */
+  (void)original_offset;
+
+  if (pypy_debug_file)
     {
-      char *filename = malloc(strlen(debug_filename) + 32);
       fclose(pypy_debug_file);
       pypy_debug_file = NULL;
-      if (filename == NULL)
-        return;   /* bah */
-      sprintf(filename, "%s.fork%ld", debug_filename, (long)getpid());
-      pypy_debug_file = fopen(filename, "w");
-      if (pypy_debug_file)
-        fprintf(pypy_debug_file, "FORKED: %ld %s\n", original_offset,
-                debug_filename_with_fork ? debug_filename_with_fork
-                                         : debug_filename);
-      free(debug_filename_with_fork);
-      debug_filename_with_fork = filename;
+      /* if PYPYLOG was set to a name with "$$" in it, it is still
+         alive, and will be reopened with the new subprocess' pid as
+         soon as it logs anything */
+      debug_ready = 0;
     }
 }
 
diff --git a/rpython/translator/c/src/debug_print.h b/rpython/translator/c/src/debug_print.h
--- a/rpython/translator/c/src/debug_print.h
+++ b/rpython/translator/c/src/debug_print.h
@@ -21,6 +21,10 @@
    subsections.
 
    Note that 'fname' can be '-' to send the logging data to stderr.
+   If 'fname' includes the substring '$$', it is replaced with the
+   current process id and you get the log for all subprocesses (and
+   forks) in different files.  If 'fname' does not include '$$', it is
+   removed from the environment and not passed to subprocesses.
 */
 
 /* macros used by the generated code */
diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py
--- a/rpython/translator/c/test/test_standalone.py
+++ b/rpython/translator/c/test/test_standalone.py
@@ -531,6 +531,7 @@
             py.test.skip("requires fork()")
 
         def entry_point(argv):
+            print "parentpid =", os.getpid()
             debug_start("foo")
             debug_print("test line")
             childpid = os.fork()
@@ -543,40 +544,46 @@
         t, cbuilder = self.compile(entry_point)
         path = udir.join('test_debug_print_fork.log')
         out, err = cbuilder.cmdexec("", err=True,
-                                    env={'PYPYLOG': ':%s' % path})
+                                    env={'PYPYLOG': ':%s.$$' % path})
         assert not err
+        import time
+        time.sleep(0.5)    # time for the forked children to finish
         #
-        f = open(str(path), 'r')
+        lines = out.splitlines()
+        assert lines[-1].startswith('parentpid = ')
+        parentpid = int(lines[-1][12:])
+        #
+        f = open('%s.%d' % (path, parentpid), 'r')
         lines = f.readlines()
         f.close()
         assert '{foo' in lines[0]
         assert lines[1] == "test line\n"
-        offset1 = len(lines[0]) + len(lines[1])
+        #offset1 = len(lines[0]) + len(lines[1])
         assert lines[2].startswith('childpid = ')
         childpid = int(lines[2][11:])
         assert childpid != 0
         assert 'foo}' in lines[3]
         assert len(lines) == 4
         #
-        f = open('%s.fork%d' % (path, childpid), 'r')
+        f = open('%s.%d' % (path, childpid), 'r')
         lines = f.readlines()
         f.close()
-        assert lines[0] == 'FORKED: %d %s\n' % (offset1, path)
-        assert lines[1] == 'childpid = 0\n'
-        offset2 = len(lines[0]) + len(lines[1])
-        assert lines[2].startswith('childpid2 = ')
-        childpid2 = int(lines[2][11:])
+        #assert lines[0] == 'FORKED: %d %s\n' % (offset1, path)
+        assert lines[0] == 'childpid = 0\n'
+        #offset2 = len(lines[0]) + len(lines[1])
+        assert lines[1].startswith('childpid2 = ')
+        childpid2 = int(lines[1][11:])
         assert childpid2 != 0
-        assert 'foo}' in lines[3]
-        assert len(lines) == 4
+        assert 'foo}' in lines[2]
+        assert len(lines) == 3
         #
-        f = open('%s.fork%d' % (path, childpid2), 'r')
+        f = open('%s.%d' % (path, childpid2), 'r')
         lines = f.readlines()
         f.close()
-        assert lines[0] == 'FORKED: %d %s.fork%d\n' % (offset2, path, childpid)
-        assert lines[1] == 'childpid2 = 0\n'
-        assert 'foo}' in lines[2]
-        assert len(lines) == 3
+        #assert lines[0] == 'FORKED: %d %s.fork%d\n' % (offset2, path, childpid)
+        assert lines[0] == 'childpid2 = 0\n'
+        assert 'foo}' in lines[1]
+        assert len(lines) == 2
 
     def test_debug_flush_at_exit(self):
         def entry_point(argv):


More information about the pypy-commit mailing list