Repository: buildbot/buildbot

Issue:
fix sqlite maxconn to 1
PR #2270, shows lots of issues related to sqlite multiprocessing.

I think this not really related to this PR, but rather related to sqlite not working well with threads.

After investigating a couple of hours, I wasn't really able to fix the issue.

I added a bunch of connection close(), but those are not really sufficient (this removes some operational errors, but not all)

putting max_conn to 1 to sqlite as default to secure 0.9.0 release, and filling this bug
http://trac.buildbot.net/ticket/3565



Discussion:

Resolving patch:
diff --git a/master/buildbot/buildslave.py b/master/buildbot/buildslave.py
--- a/master/buildbot/buildslave.py
+++ b/master/buildbot/buildslave.py
@@ -176,6 +176,12 @@ def _lockReleased(self):
             return # oh well..
         self.botmaster.maybeStartBuildsForSlave(self.slavename)
 
+    def setServiceParent(self, parent):
+        # botmaster needs to set before setServiceParent which calls startService
+        self.botmaster = parent
+        self.master = parent.master
+        service.MultiService.setServiceParent(self, parent)
+
     def startService(self):
         self.updateLocks()
         self.startMissingTimer()
diff --git a/master/buildbot/process/botmaster.py b/master/buildbot/process/botmaster.py
--- a/master/buildbot/process/botmaster.py
+++ b/master/buildbot/process/botmaster.py
@@ -224,9 +224,6 @@ def reconfigServiceSlaves(self, new_config):
             for n in added_names:
                 slave = new_by_name[n]
                 slave.setServiceParent(self)
-
-                slave.botmaster = self
-                slave.master = self.master
                 self.slaves[n] = slave
 
         metrics.MetricCountEvent.log("num_slaves",


Test patch:
diff --git a/master/buildbot/test/fake/botmaster.py b/master/buildbot/test/fake/botmaster.py
new file mode 100644
--- /dev/null
+++ b/master/buildbot/test/fake/botmaster.py
@@ -0,0 +1,32 @@
+# This file is part of Buildbot.  Buildbot is free software: you can
+# redistribute it and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation, version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright Buildbot Team Members
+
+from twisted.application import service
+
+class FakeBotMaster(service.MultiService):
+    def __init__(self, master):
+        service.MultiService.__init__(self)
+        self.setName("fake-botmaster")
+        self.master = master
+        self.locks = {}
+
+    def getLockByID(self, lockid):
+        if not lockid in self.locks:
+            self.locks[lockid] = lockid.lockClass(lockid)
+        # if the master.cfg file has changed maxCount= on the lock, the next
+        # time a build is started, they'll get a new RealLock instance. Note
+        # that this requires that MasterLock and SlaveLock (marker) instances
+        # be hashable and that they should compare properly.
+        return self.locks[lockid]
diff --git a/master/buildbot/test/unit/test_buildslave.py b/master/buildbot/test/unit/test_buildslave.py
--- a/master/buildbot/test/unit/test_buildslave.py
+++ b/master/buildbot/test/unit/test_buildslave.py
@@ -16,10 +16,11 @@
 import mock
 from twisted.trial import unittest
 from twisted.internet import defer
-from buildbot import buildslave, config
+from buildbot import buildslave, config, locks
 from buildbot.test.fake import fakemaster, pbmanager
+from buildbot.test.fake.botmaster import FakeBotMaster
 
-class AbstractBuildSlave(unittest.TestCase):
+class TestAbstractBuildSlave(unittest.TestCase):
 
     class ConcreteBuildSlave(buildslave.AbstractBuildSlave):
         pass
@@ -216,3 +217,35 @@ def test_missing_timer(self):
         bs.stopMissingTimer()
         self.assertEqual(bs.missing_timer, None)
 
+    def test_setServiceParent_started(self):
+        master = self.master = fakemaster.make_master()
+        botmaster = FakeBotMaster(master)
+        botmaster.startService()
+        bs = self.ConcreteBuildSlave('bot', 'pass')
+        bs.setServiceParent(botmaster)
+        self.assertEqual(bs.botmaster, botmaster)
+        self.assertEqual(bs.master, master)
+
+    def test_setServiceParent_masterLocks(self):
+        """
+        http://trac.buildbot.net/ticket/2278
+        """
+        master = self.master = fakemaster.make_master()
+        botmaster = FakeBotMaster(master)
+        botmaster.startService()
+        lock = locks.MasterLock('masterlock')
+        bs = self.ConcreteBuildSlave('bot', 'pass', locks = [lock])
+        bs.setServiceParent(botmaster)
+
+    def test_setServiceParent_slaveLocks(self):
+        """
+        http://trac.buildbot.net/ticket/2278
+        """
+        master = self.master = fakemaster.make_master()
+        botmaster = FakeBotMaster(master)
+        botmaster.startService()
+        lock = locks.SlaveLock('lock')
+        bs = self.ConcreteBuildSlave('bot', 'pass', locks = [lock])
+        bs.setServiceParent(botmaster)
+
+    test_setServiceParent_slaveLocks.todo = "SlaveLock not support for slave lock"
diff --git a/master/buildbot/test/unit/test_process_botmaster_BotMaster.py b/master/buildbot/test/unit/test_process_botmaster_BotMaster.py
--- a/master/buildbot/test/unit/test_process_botmaster_BotMaster.py
+++ b/master/buildbot/test/unit/test_process_botmaster_BotMaster.py
@@ -168,7 +168,6 @@ def test_reconfigServiceSlaves_add_remove(self):
         wfd.getResult()
 
         self.assertIdentical(sl.parent, self.botmaster)
-        self.assertIdentical(sl.master, self.master)
         self.assertEqual(self.botmaster.slaves, { 'sl1' : sl })
 
         self.new_config.slaves = [ ]