[pypy-commit] pypy default: Merge sandbox tweaks from nedbat-sandbox-2

ned noreply at buildbot.pypy.org
Wed Dec 28 15:26:10 CET 2011


Author: Ned Batchelder <ned at nedbatchelder.com>
Branch: 
Changeset: r50926:42fbbcbfc2ac
Date: 2011-12-28 09:25 -0500
http://bitbucket.org/pypy/pypy/changeset/42fbbcbfc2ac/

Log:	Merge sandbox tweaks from nedbat-sandbox-2

diff --git a/pypy/translator/sandbox/pypy_interact.py b/pypy/translator/sandbox/pypy_interact.py
--- a/pypy/translator/sandbox/pypy_interact.py
+++ b/pypy/translator/sandbox/pypy_interact.py
@@ -13,7 +13,8 @@
                   ATM this only works with PyPy translated with Boehm or
                   the semispace or generation GCs.
     --timeout=N   limit execution time to N (real-time) seconds.
-    --log=FILE    log all user input into the FILE
+    --log=FILE    log all user input into the FILE.
+    --verbose     log all proxied system calls.
 
 Note that you can get readline-like behavior with a tool like 'ledit',
 provided you use enough -u options:
@@ -30,15 +31,15 @@
 LIB_ROOT = os.path.dirname(os.path.dirname(pypy.__file__))
 
 class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc):
-    debug = True
     argv0 = '/bin/pypy-c'
     virtual_cwd = '/tmp'
     virtual_env = {}
     virtual_console_isatty = True
 
-    def __init__(self, executable, arguments, tmpdir=None):
+    def __init__(self, executable, arguments, tmpdir=None, debug=True):
         self.executable = executable = os.path.abspath(executable)
         self.tmpdir = tmpdir
+        self.debug = debug
         super(PyPySandboxedProc, self).__init__([self.argv0] + arguments,
                                                 executable=executable)
 
@@ -68,12 +69,13 @@
 
 if __name__ == '__main__':
     from getopt import getopt      # and not gnu_getopt!
-    options, arguments = getopt(sys.argv[1:], 't:h', 
+    options, arguments = getopt(sys.argv[1:], 't:hv', 
                                 ['tmp=', 'heapsize=', 'timeout=', 'log=',
-                                 'help'])
+                                 'verbose', 'help'])
     tmpdir = None
     timeout = None
     logfile = None
+    debug = False
     extraoptions = []
 
     def help():
@@ -105,6 +107,8 @@
             timeout = int(value)
         elif option == '--log':
             logfile = value
+        elif option in ['-v', '--verbose']:
+            debug = True
         elif option in ['-h', '--help']:
             help()
         else:
@@ -114,7 +118,7 @@
         help()
 
     sandproc = PyPySandboxedProc(arguments[0], extraoptions + arguments[1:],
-                                 tmpdir=tmpdir)
+                                 tmpdir=tmpdir, debug=debug)
     if timeout is not None:
         sandproc.settimeout(timeout, interrupt_main=True)
     if logfile is not None:
diff --git a/pypy/translator/sandbox/sandlib.py b/pypy/translator/sandbox/sandlib.py
--- a/pypy/translator/sandbox/sandlib.py
+++ b/pypy/translator/sandbox/sandlib.py
@@ -4,25 +4,29 @@
 for the outer process, which can run CPython or PyPy.
 """
 
-import py
 import sys, os, posixpath, errno, stat, time
-from pypy.tool.ansi_print import AnsiLog
 import subprocess
 from pypy.tool.killsubprocess import killsubprocess
 from pypy.translator.sandbox.vfs import UID, GID
+import py
 
-class MyAnsiLog(AnsiLog):
-    KW_TO_COLOR = {
-        'call': ((34,), False),
-        'result': ((34,), False),
-        'exception': ((34,), False),
-        'vpath': ((35,), False),
-        'timeout': ((1, 31), True),
-        }
+def create_log():
+    """Make and return a log for the sandbox to use, if needed."""
+    # These imports are local to avoid importing pypy if we don't need to.
+    from pypy.tool.ansi_print import AnsiLog
 
-log = py.log.Producer("sandlib")
-py.log.setconsumer("sandlib", MyAnsiLog())
+    class MyAnsiLog(AnsiLog):
+        KW_TO_COLOR = {
+            'call': ((34,), False),
+            'result': ((34,), False),
+            'exception': ((34,), False),
+            'vpath': ((35,), False),
+            'timeout': ((1, 31), True),
+            }
 
+    log = py.log.Producer("sandlib")
+    py.log.setconsumer("sandlib", MyAnsiLog())
+    return log
 
 # Note: we use lib_pypy/marshal.py instead of the built-in marshal
 # for two reasons.  The built-in module could be made to segfault
@@ -127,6 +131,7 @@
     for the external functions xxx that you want to support.
     """
     debug = False
+    log = None
     os_level_sandboxing = False   # Linux only: /proc/PID/seccomp
 
     def __init__(self, args, executable=None):
@@ -143,6 +148,9 @@
         self.currenttimeout = None
         self.currentlyidlefrom = None
 
+        if self.debug:
+            self.log = create_log()
+
     def withlock(self, function, *args, **kwds):
         lock = self.popenlock
         if lock is not None:
@@ -170,7 +178,8 @@
                 if delay <= 0.0:
                     break   # expired!
                 time.sleep(min(delay*1.001, 1))
-            log.timeout("timeout!")
+            if self.log:
+                self.log.timeout("timeout!")
             self.kill()
             #if interrupt_main:
             #    if hasattr(os, 'kill'):
@@ -247,22 +256,22 @@
                 args   = read_message(child_stdout)
             except EOFError, e:
                 break
-            if self.debug and not self.is_spam(fnname, *args):
-                log.call('%s(%s)' % (fnname,
+            if self.log and not self.is_spam(fnname, *args):
+                self.log.call('%s(%s)' % (fnname,
                                      ', '.join([shortrepr(x) for x in args])))
             try:
                 answer, resulttype = self.handle_message(fnname, *args)
             except Exception, e:
                 tb = sys.exc_info()[2]
                 write_exception(child_stdin, e, tb)
-                if self.debug:
+                if self.log:
                     if str(e):
-                        log.exception('%s: %s' % (e.__class__.__name__, e))
+                        self.log.exception('%s: %s' % (e.__class__.__name__, e))
                     else:
-                        log.exception('%s' % (e.__class__.__name__,))
+                        self.log.exception('%s' % (e.__class__.__name__,))
             else:
-                if self.debug and not self.is_spam(fnname, *args):
-                    log.result(shortrepr(answer))
+                if self.log and not self.is_spam(fnname, *args):
+                    self.log.result(shortrepr(answer))
                 try:
                     write_message(child_stdin, 0)  # error code - 0 for ok
                     write_message(child_stdin, answer, resulttype)
@@ -441,7 +450,8 @@
             node = dirnode.join(name)
         else:
             node = dirnode
-        log.vpath('%r => %r' % (vpath, node))
+        if self.log:
+            self.log.vpath('%r => %r' % (vpath, node))
         return node
 
     def do_ll_os__ll_os_stat(self, vpathname):


More information about the pypy-commit mailing list