[pypy-commit] pypy default: (fijal, arigo)
arigo
noreply at buildbot.pypy.org
Fri Aug 23 18:19:40 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r66304:9b31edfc3a5b
Date: 2013-08-23 18:17 +0200
http://bitbucket.org/pypy/pypy/changeset/9b31edfc3a5b/
Log: (fijal, arigo)
Using "PYPYLOG=..:filename", on any fork(), it will now create a new
file "filename.forkCHILDPID", starting with
FORKED: <position> <parent filename>
diff --git a/rpython/rlib/debug.py b/rpython/rlib/debug.py
--- a/rpython/rlib/debug.py
+++ b/rpython/rlib/debug.py
@@ -196,6 +196,25 @@
return hop.genop('debug_flush', [])
+def debug_forked(original_offset):
+ """ Call after a fork(), passing as argument the result of
+ debug_offset() called before the fork.
+ """
+ pass
+
+class Entry(ExtRegistryEntry):
+ _about_ = debug_forked
+
+ def compute_result_annotation(self, s_original_offset):
+ return None
+
+ def specialize_call(self, hop):
+ from rpython.rtyper.lltypesystem import lltype
+ vlist = hop.inputargs(lltype.Signed)
+ hop.exception_cannot_occur()
+ return hop.genop('debug_forked', vlist)
+
+
def llinterpcall(RESTYPE, pythonfunction, *args):
"""When running on the llinterp, this causes the llinterp to call to
the provided Python function with the run-time value of the given args.
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -1566,7 +1566,7 @@
@registering_if(os, 'fork')
def register_os_fork(self):
- from rpython.rlib import rthread
+ from rpython.rlib import rthread, debug
eci = self.gcc_profiling_bug_workaround('pid_t _noprof_fork(void)',
'return fork();')
os_fork = self.llexternal('_noprof_fork', [], rffi.PID_T,
@@ -1575,11 +1575,14 @@
def fork_llimpl():
# NB. keep forkpty() up-to-date, too
+ ofs = debug.debug_offset()
opaqueaddr = rthread.gc_thread_before_fork()
childpid = rffi.cast(lltype.Signed, os_fork())
rthread.gc_thread_after_fork(childpid, opaqueaddr)
if childpid == -1:
raise OSError(rposix.get_errno(), "os_fork failed")
+ if childpid == 0:
+ debug.debug_forked(ofs)
return rffi.cast(lltype.Signed, childpid)
return extdef([], int, llimpl=fork_llimpl,
@@ -1619,6 +1622,7 @@
def forkpty_llimpl():
master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
master_p[0] = rffi.cast(rffi.INT, -1)
+ ofs = debug.debug_offset()
opaqueaddr = rthread.gc_thread_before_fork()
childpid = rffi.cast(lltype.Signed,
os_forkpty(master_p, None, None, None))
@@ -1627,6 +1631,8 @@
lltype.free(master_p, flavor='raw')
if childpid == -1:
raise OSError(rposix.get_errno(), "os_forkpty failed")
+ if childpid == 0:
+ debug.debug_forked(ofs)
return (rffi.cast(lltype.Signed, childpid),
rffi.cast(lltype.Signed, master_fd))
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,16 +23,12 @@
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(void)
{
char *filename = getenv("PYPYLOG");
- if (filename)
-#ifndef _WIN32
- unsetenv("PYPYLOG"); /* don't pass it to subprocesses */
-#else
- putenv("PYPYLOG="); /* don't pass it to subprocesses */
-#endif
if (filename && filename[0])
{
char *colon = strchr(filename, ':');
@@ -52,7 +48,10 @@
filename = colon + 1;
}
if (strcmp(filename, "-") != 0)
- pypy_debug_file = fopen(filename, "w");
+ {
+ debug_filename = strdup(filename);
+ pypy_debug_file = fopen(filename, "w");
+ }
}
if (!pypy_debug_file)
{
@@ -64,6 +63,12 @@
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;
}
@@ -73,6 +78,7 @@
return -1;
// note that we deliberately ignore errno, since -1 is fine
// in case this is not a real file
+ fflush(pypy_debug_file);
return ftell(pypy_debug_file);
}
@@ -82,6 +88,26 @@
pypy_debug_open();
}
+void pypy_debug_forked(long original_offset)
+{
+ if (debug_filename != NULL)
+ {
+ 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;
+ }
+}
+
#ifndef _WIN32
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
@@ -29,6 +29,7 @@
#define PYPY_DEBUG_START(cat) pypy_debug_start(cat)
#define PYPY_DEBUG_STOP(cat) pypy_debug_stop(cat)
#define OP_DEBUG_OFFSET(res) res = pypy_debug_offset()
+#define OP_DEBUG_FORKED(ofs, _) pypy_debug_forked(ofs)
#define OP_HAVE_DEBUG_PRINTS(r) r = (pypy_have_debug_prints & 1)
#define OP_DEBUG_FLUSH() fflush(pypy_debug_file)
@@ -39,6 +40,7 @@
void pypy_debug_start(const char *category);
void pypy_debug_stop(const char *category);
long pypy_debug_offset(void);
+void pypy_debug_forked(long original_offset);
extern long pypy_have_debug_prints;
extern FILE *pypy_debug_file;
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
@@ -447,6 +447,57 @@
assert 'bar' == lines[1]
assert 'foo}' in lines[2]
+ def test_debug_print_fork(self):
+ if not hasattr(os, 'fork'):
+ py.test.skip("requires fork()")
+
+ def entry_point(argv):
+ debug_start("foo")
+ debug_print("test line")
+ childpid = os.fork()
+ debug_print("childpid =", childpid)
+ if childpid == 0:
+ childpid2 = os.fork() # double-fork
+ debug_print("childpid2 =", childpid2)
+ debug_stop("foo")
+ return 0
+ t, cbuilder = self.compile(entry_point)
+ path = udir.join('test_debug_print_fork.log')
+ out, err = cbuilder.cmdexec("", err=True,
+ env={'PYPYLOG': ':%s' % path})
+ assert not err
+ #
+ f = open(str(path), 'r')
+ lines = f.readlines()
+ f.close()
+ assert '{foo' in lines[0]
+ assert lines[1] == "test line\n"
+ 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')
+ 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 childpid2 != 0
+ assert 'foo}' in lines[3]
+ assert len(lines) == 4
+ #
+ f = open('%s.fork%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
def test_fatal_error(self):
def g(x):
More information about the pypy-commit
mailing list