Repository: buildbot/buildbot

Issue:
Remove remaining sa.Table invocations
With a check in validate to be sure!



Discussion:

Resolving patch:
diff --git a/master/buildbot/scripts/start.py b/master/buildbot/scripts/start.py
--- a/master/buildbot/scripts/start.py
+++ b/master/buildbot/scripts/start.py
@@ -16,7 +16,7 @@
 
 import os, sys, time
 from buildbot.scripts import base
-from twisted.internet import reactor
+from twisted.internet import reactor, protocol
 from twisted.python.runtime import platformType
 from buildbot.scripts.logwatcher import LogWatcher
 from buildbot.scripts.logwatcher import BuildmasterTimeoutError
@@ -59,20 +59,15 @@ def _failure(self, why):
         self.rc = 1
         reactor.stop()
 
-
-def launch(config):
+def launchNoDaemon(config):
     os.chdir(config['basedir'])
     sys.path.insert(0, os.path.abspath(config['basedir']))
 
-    # see if we can launch the application without actually having to
-    # spawn twistd, since spawning processes correctly is a real hassle
-    # on windows.
     argv = ["twistd",
             "--no_save",
+            '--nodaemon',
             "--logfile=twistd.log", # windows doesn't use the same default
             "--python=buildbot.tac"]
-    if config['nodaemon']:
-        argv.extend(['--nodaemon'])
     sys.argv = argv
 
     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
@@ -81,28 +76,41 @@ def launch(config):
     from twisted.scripts import twistd
     twistd.run()
 
+def launch(config):
+    os.chdir(config['basedir'])
+    sys.path.insert(0, os.path.abspath(config['basedir']))
+
+    # see if we can launch the application without actually having to
+    # spawn twistd, since spawning processes correctly is a real hassle
+    # on windows.
+    argv = [sys.executable,
+            "-c",
+            # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
+            # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for
+            # windows.
+            "from twisted.scripts import twistd; twistd.run()",
+            "--no_save",
+            "--logfile=twistd.log", # windows doesn't use the same default
+            "--python=buildbot.tac"]
+
+    # ProcessProtocol just ignores all output
+    reactor.spawnProcess(protocol.ProcessProtocol(), sys.executable, argv, env=os.environ)
+
 def start(config):
     if not base.isBuildmasterDir(config['basedir']):
         print "not a buildmaster directory"
         return 1
 
-    if config['quiet']:
-        launch(config)
-        return 0
-
-    # we probably can't do this os.fork under windows
-    if platformType == "win32":
-        launch(config)
+    if config['nodaemon']:
+        launchNoDaemon(config)
         return 0
 
-    # fork a child to launch the daemon, while the parent process tails the
-    # logfile
-    if os.fork():
-        # this is the parent
-        rc = Follower().follow(config['basedir'])
-        return rc
-    # this is the child: give the logfile-watching parent a chance to start
-    # watching it before we start the daemon
-    time.sleep(0.2)
     launch(config)
 
+    # We don't have tail on windows
+    if platformType == "win32" or config['quiet']:
+        return 0
+
+    # this is the parent
+    rc = Follower().follow(config['basedir'])
+    return rc


Test patch:
diff --git a/master/buildbot/test/unit/test_scripts_start.py b/master/buildbot/test/unit/test_scripts_start.py
--- a/master/buildbot/test/unit/test_scripts_start.py
+++ b/master/buildbot/test/unit/test_scripts_start.py
@@ -15,13 +15,18 @@
 
 from __future__ import with_statement
 
-import os
+import os, sys
+from twisted.internet.utils import getProcessOutputAndValue
 from twisted.trial import unittest
 from buildbot.scripts import start
-from buildbot.test.util import dirs, misc
+from buildbot.test.util import dirs, misc, compat
 
 def mkconfig(**kwargs):
-    config = dict(quiet=False, basedir=os.path.abspath('basedir'))
+    config = {
+            'quiet': False,
+            'basedir': os.path.abspath('basedir'),
+            'nodaemon': False,
+            }
     config.update(kwargs)
     return config
 
@@ -32,6 +37,7 @@ def mkconfig(**kwargs):
 application = service.Application('highscore')
 class App(service.Service):
     def startService(self):
+        service.Service.startService(self)
         log.msg("BuildMaster is running") # heh heh heh
         reactor.callLater(0, reactor.stop)
 app = App()
@@ -56,6 +62,40 @@ def test_start_not_basedir(self):
         self.assertEqual(start.start(mkconfig(basedir='doesntexist')), 1)
         self.assertInStdout('not a buildmaster directory')
 
+    def runStart(self, **config):
+        args=[
+                '-c',
+                'from buildbot.scripts.start import start; start(%r)' % (mkconfig(**config),),
+                ]
+        env = os.environ.copy()
+        env['PYTHONPATH'] = os.pathsep.join(sys.path)
+        return getProcessOutputAndValue(sys.executable, args=args, env=env)
+
+    def test_start_no_daemon(self):
+        d = self.runStart(nodaemon=True)
+        @d.addCallback
+        def cb(res):
+            self.assertEquals(res, ('', '', 0))
+            print res
+        return d
+
+    def test_start_quiet(self):
+        d = self.runStart(quiet=True)
+        @d.addCallback
+        def cb(res):
+            self.assertEquals(res, ('', '', 0))
+            print res
+        return d
+
+    @compat.skipUnlessPlatformIs('posix')
+    def test_start(self):
+        d = self.runStart()
+        @d.addCallback
+        def cb((out, err, rc)):
+            self.assertEqual((rc, err), (0, ''))
+            self.assertSubstring('BuildMaster is running', out)
+        return d
+
     # the remainder of this script does obscene things:
     #  - forks
     #  - shells out to tail