[pypy-svn] r40529 - in pypy/dist/pypy: bin tool/build tool/build/web tool/build/web/test

guido at codespeak.net guido at codespeak.net
Thu Mar 15 14:46:23 CET 2007


Author: guido
Date: Thu Mar 15 14:46:21 2007
New Revision: 40529

Modified:
   pypy/dist/pypy/bin/buildserver.py
   pypy/dist/pypy/tool/build/metaserver.py
   pypy/dist/pypy/tool/build/web/app.py
   pypy/dist/pypy/tool/build/web/test/test_app.py
Log:
Fixed nasty cleanup issues in web server, small fix (making sure channel gets
closed properly) in buildserver shell script too.


Modified: pypy/dist/pypy/bin/buildserver.py
==============================================================================
--- pypy/dist/pypy/bin/buildserver.py	(original)
+++ pypy/dist/pypy/bin/buildserver.py	Thu Mar 15 14:46:21 2007
@@ -27,39 +27,41 @@
         sys.stderr = outbuffer
         try:
             try:
-                from pypy.interpreter.error import OperationError
-                from pypy.translator.goal import targetpypystandalone
-                from pypy.translator.driver import TranslationDriver
-                from pypy.config import pypyoption
-                from pypy.tool.udir import udir
-
-                config = pypyoption.get_pypy_config()
-                config.override(compileinfo)
-
-                driver = TranslationDriver.from_targetspec(
-                            targetpypystandalone.__dict__, config=config,
-                            default_goal='compile')
-                driver.proceed(['compile'])
-            except Exception, e:
-                # XXX we may want to check
-                exception_occurred = True
-                exc, e, tb = sys.exc_info()
-                print '=' * 79
-                print 'Exception during compilation:'
-                print '%%s: %%s' %% (exc, e)
-                print
-                print '\\n'.join(traceback.format_tb(tb))
-                print '=' * 79
-                del tb
-                channel.send(None)
-            else:
-                channel.send(str(udir))
+                try:
+                    from pypy.interpreter.error import OperationError
+                    from pypy.translator.goal import targetpypystandalone
+                    from pypy.translator.driver import TranslationDriver
+                    from pypy.config import pypyoption
+                    from pypy.tool.udir import udir
+
+                    config = pypyoption.get_pypy_config()
+                    config.override(compileinfo)
+
+                    driver = TranslationDriver.from_targetspec(
+                                targetpypystandalone.__dict__, config=config,
+                                default_goal='compile')
+                    driver.proceed(['compile'])
+                except Exception, e:
+                    # XXX we may want to check
+                    exception_occurred = True
+                    exc, e, tb = sys.exc_info()
+                    print '=' * 79
+                    print 'Exception during compilation:'
+                    print '%%s: %%s' %% (exc, e)
+                    print
+                    print '\\n'.join(traceback.format_tb(tb))
+                    print '=' * 79
+                    del tb
+                    channel.send(None)
+                else:
+                    channel.send(str(udir))
+            finally:
+                sys.stdout = sys.__stdout__
+                sys.stderr = sys.__stderr__
+                log.close()
+            channel.send(outbuffer.getvalue())
         finally:
-            sys.stdout = sys.__stdout__
-            sys.stderr = sys.__stderr__
-            log.close()
-        channel.send(outbuffer.getvalue())
-        channel.close()
+            channel.close()
     """
     gw = PopenGateway()
     interpolated = py.code.Source(outputbuffer,

Modified: pypy/dist/pypy/tool/build/metaserver.py
==============================================================================
--- pypy/dist/pypy/tool/build/metaserver.py	(original)
+++ pypy/dist/pypy/tool/build/metaserver.py	Thu Mar 15 14:46:21 2007
@@ -294,18 +294,12 @@
 
             server.serve_forever()
         except:
-            try:
-                import sys, traceback
-                exc, e, tb = sys.exc_info()
-                channel.send(str(exc) + ' - ' + str(e))
-                for line in traceback.format_tb(tb):
-                    channel.send(line[:1])
-                del tb
-            except:
-                try:
-                    channel.close()
-                except:
-                    pass
+            import sys, traceback
+            exc, e, tb = sys.exc_info()
+            channel.send(str(exc) + ' - ' + str(e))
+            for line in traceback.format_tb(tb):
+                channel.send(line[:1])
+            del tb
     finally:
         channel.close()
 """

Modified: pypy/dist/pypy/tool/build/web/app.py
==============================================================================
--- pypy/dist/pypy/tool/build/web/app.py	(original)
+++ pypy/dist/pypy/tool/build/web/app.py	Thu Mar 15 14:46:21 2007
@@ -69,19 +69,46 @@
         return "\n  ".join(items)
     return "<ul> %s </ul>" % (add(config, outermost=False), )
 
-
 class ServerPage(object):
     """ base class for pages that communicate with the server
     """
     exposed = True
-    _calllock = py.std.thread.allocate_lock()
-    _channel_holder = []
-    _result_cache = {}
     MAX_CACHE_TIME = 30 # seconds
+    _shared = {
+        'lock': py.std.thread.allocate_lock(),
+        'channel': None,
+        'gateway': None,
+        'result_cache': {},
+        'initialized': False,
+    }
 
     def __init__(self, config, gateway=None):
         self.config = config
-        self.gateway = gateway or self.init_gateway()
+        self.gateway = gateway
+        self._shared['lock'].acquire()
+        try:
+            self._init_shared(gateway)
+        finally:
+            self._shared['lock'].release()
+
+    def _init_shared(self, gateway=None):
+        if self._shared['initialized']:
+            return self._shared['channel']
+        self._shared['gateway'] = gateway = gateway or self.init_gateway()
+        self._shared['conference'] = conf = \
+            execnetconference.conference(gateway, self.config.port, False)
+        self._shared['channel'] = chan = conf.remote_exec(self.remote_code % (
+                                                          self.config.path,))
+        self._shared['initialized'] = True
+        return chan
+
+    def _cleanup_shared(self):
+        self._shared['channel'].close()
+        self._shared['gateway'].exit()
+        self._shared['channel'] = None
+        self._shared['gateway'] = None
+        self._shared['initialized'] = False
+        self.gateway = None
 
     remote_code = """
         import sys
@@ -89,11 +116,11 @@
 
         from pypy.tool.build import metaserver_instance
         from pypy.tool.build.web.app import MetaServerAccessor
-        msi = MetaServerAccessor(metaserver_instance)
+        msa = MetaServerAccessor(metaserver_instance)
         while 1:
             try:
                 methodname, args = channel.receive()
-                ret = getattr(msi, methodname)(*args)
+                ret = getattr(msa, methodname)(*args)
                 channel.send(ret)
             except IOError: # XXX anything else?
                 break
@@ -107,18 +134,18 @@
             careful with args, as it's used as dict key for caching (and
             also sent over the wire) so should be fairly simple
         """
-        self._calllock.acquire()
+        self._shared['lock'].acquire()
         try:
             try:
-                time, value = self._result_cache[(methodname, args)]
+                ctime, value = self._shared['result_cache'][(methodname, args)]
             except KeyError:
                 pass
             else:
-                if time > py.std.time.time() - self.MAX_CACHE_TIME:
+                if ctime > time.time() - self.MAX_CACHE_TIME:
                     return value
             performed = False
-            if self._channel_holder:
-                channel = self._channel_holder[0]
+            if self._shared['channel']:
+                channel = self._shared['channel']
                 try:
                     channel.send((methodname, args))
                     ret = channel.receive()
@@ -127,22 +154,22 @@
                     del tb
                     print ('exception occurred when calling %s(%s): '
                            '%s - %s' % (methodname, args, exc, e))
+                    try:
+                        self._cleanup_shared()
+                    except:
+                        exc, e, tb = sys.exc_info()
+                        print 'errors during cleanup: %s - %s' % (exc, e)
                 else:
                     performed = True
             if not performed:
-                conference = execnetconference.conference(self.gateway,
-                                                          self.config.port, False)
-                channel = conference.remote_exec(self.remote_code % (
-                                                 self.config.path,))
+                channel = self._init_shared(self.gateway)
                 channel.send((methodname, args))
                 ret = channel.receive()
-                while self._channel_holder:
-                    self._channel_holder.pop()
-                self._channel_holder.append(channel)
-            self._result_cache[(methodname, args)] = (py.std.time.time(), ret)
+            self._shared['result_cache'][(methodname, args)] = (time.time(),
+                                                                ret)
             return ret
         finally:
-            self._calllock.release()
+            self._shared['lock'].release()
     
     def init_gateway(self):
         if self.config.server in ['localhost', '127.0.0.1']:

Modified: pypy/dist/pypy/tool/build/web/test/test_app.py
==============================================================================
--- pypy/dist/pypy/tool/build/web/test/test_app.py	(original)
+++ pypy/dist/pypy/tool/build/web/test/test_app.py	Thu Mar 15 14:46:21 2007
@@ -310,36 +310,37 @@
 
 class TestServerPage(object):
     def test_call_method_simple(self):
-        p = ServerPage(fake.Container(port=build_config.testport, path=str(path)),
-                       py.execnet.PopenGateway())
+        p = ServerPage(fake.Container(port=build_config.testport,
+                                      path=str(path)),
+                       gateway)
         ret = p.call_method('status', ())
         assert ret
 
     def test_call_method_reconnect(self):
-        p = ServerPage(fake.Container(port=build_config.testport, path=str(path)),
-                       py.execnet.PopenGateway())
+        p = ServerPage(fake.Container(port=build_config.testport,
+                                      path=str(path), server='127.0.0.1'))
         ret = p.call_method('status', ())
-        assert len(p._channel_holder) == 1
-        channel = p._channel_holder[0]
+        channel = p._shared['channel']
+        assert channel is not None
         
         ret = p.call_method('status', ())
-        assert len(p._channel_holder) == 1
-        assert p._channel_holder[0] is channel
+        assert p._shared['channel'] is channel
         channel.close()
 
         ret = p.call_method('status', ())
-        assert len(p._channel_holder) == 1
-        assert p._channel_holder is not channel
+        assert p._shared['channel'] is not None
+        assert p._shared['channel'] is not channel
 
     def test_call_method_cache(self):
-        p = ServerPage(fake.Container(port=build_config.testport, path=str(path)),
-                       py.execnet.PopenGateway())
-        p._result_cache = {}
+        p = ServerPage(fake.Container(port=build_config.testport,
+                                      path=str(path)),
+                       gateway)
+        p._shared['result_cache'] = {}
         p.MAX_CACHE_TIME = 1000
         try:
             ret = p.call_method('status', ())
-            assert len(p._result_cache) == 1
-            cached = p._result_cache.get(('status', ()))
+            assert len(p._shared['result_cache']) == 1
+            cached = p._shared['result_cache'].get(('status', ()))
             assert cached[1] is ret
         finally:
             p.MAX_CACHE_TIME = -1



More information about the Pypy-commit mailing list