prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  UnboundLocalError in mq/base.py on master shutdown
  Hello,
  
  We're using buildbot in multi-master mode and got this stacktrace on one of the master when shutting it down:
  ```
  2017-07-17 12:33:29+0000 [-] Waiting for 1 build(s) to finish
  2017-07-17 12:33:29+0000 [-] Builder <Builder 'u'sql-monitor-bitbucket_scality_ring-monitor_ring_frequent-prod-frontend-0'' at 140555339856784> has 1 builds running
  2017-07-17 12:33:29+0000 [-] Not shutting down, there are 1 builds running
  2017-07-17 12:33:29+0000 [-] Trying shutdown sequence again
  2017-07-17 12:33:30+0000 [-] <Build sql-monitor-bitbucket_scality_ring-monitor_ring_frequent-prod-frontend-0 number:32108L results:exception>: stopping build: Master Shutdown 5
  2017-07-17 12:33:30+0000 [-] Unhandled error in Deferred:
  2017-07-17 12:33:30+0000 [-] Unhandled Error
  Traceback (most recent call last):
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1299, in _inlineCallbacks
  result = g.send(result)
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/process/botmaster.py", line 105, in cleanShutdown
  l.append(build.waitUntilFinished())
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/process/build.py", line 687, in waitUntilFinished
  lambda: self.finished)
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1445, in unwindGenerator
  return _inlineCallbacks(None, gen, Deferred())
  — <exception caught here> —
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1299, in _inlineCallbacks
  result = g.send(result)
  File "/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/mq/base.py", line 40, in waitUntilEvent
  defer.returnValue(res)
  exceptions.UnboundLocalError: local variable 'res' referenced before assignment
  ```
  Looking at the code at the end of `waitUntilEvent()`:
  ```
          if not check:
              res = yield d
          yield buildCompleteConsumer.stopConsuming
          defer.returnValue(res)
  ```
  
  If the check returned false, we try to return a value (`res`) that was never defined.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `master/buildbot/mq/base.py`
  Content:
  ```
  1 # This file is part of Buildbot.  Buildbot is free software: you can
  2 # redistribute it and/or modify it under the terms of the GNU General Public
  3 # License as published by the Free Software Foundation, version 2.
  4 #
  5 # This program is distributed in the hope that it will be useful, but WITHOUT
  6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  8 # details.
  9 #
  10 # You should have received a copy of the GNU General Public License along with
  11 # this program; if not, write to the Free Software Foundation, Inc., 51
  12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  13 #
  14 # Copyright Buildbot Team Members
  15 
  16 from __future__ import absolute_import
  17 from __future__ import print_function
  18 
  19 from twisted.internet import defer
  20 from twisted.python import failure
  21 from twisted.python import log
  22 
  23 from buildbot.util import service
  24 
  25 
  26 class MQBase(service.AsyncService):
  27     name = 'mq-implementation'
  28 
  29     @defer.inlineCallbacks
  30     def waitUntilEvent(self, filter, check_callback):
  31         d = defer.Deferred()
  32         buildCompleteConsumer = yield self.startConsuming(
  33             lambda key, value: d.callback((key, value)),
  34             filter)
  35         check = yield check_callback()
  36         # we only wait if the check callback return true
  37         if not check:
  38             res = yield d
  39         yield buildCompleteConsumer.stopConsuming
  40         defer.returnValue(res)
  41 
  42 
  43 class QueueRef(object):
  44 
  45     __slots__ = ['callback']
  46 
  47     def __init__(self, callback):
  48         self.callback = callback
  49 
  50     def invoke(self, routing_key, data):
  51         if not self.callback:
  52             return
  53 
  54         try:
  55             x = self.callback(routing_key, data)
  56         except Exception:
  57             log.err(failure.Failure(), 'while invoking %r' % (self.callback,))
  58             return
  59         if isinstance(x, defer.Deferred):
  60             x.addErrback(log.err, 'while invoking %r' % (self.callback,))
  61 
  62     def stopConsuming(self):
  63         # subclasses should set self.callback to None in this method
  64         raise NotImplementedError
  65
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/master/buildbot/mq/base.py b/master/buildbot/mq/base.py
  --- a/master/buildbot/mq/base.py
  +++ b/master/buildbot/mq/base.py
  @@ -36,7 +36,9 @@
           # we only wait if the check callback return true
           if not check:
               res = yield d
  -        yield buildCompleteConsumer.stopConsuming
  +        else:
  +            res = None
  +        yield buildCompleteConsumer.stopConsuming()
           defer.returnValue(res)
  
verification_info: {"golden_diff": "diff --git a/master/buildbot/mq/base.py b/master/buildbot/mq/base.py\n--- a/master/buildbot/mq/base.py\n+++ b/master/buildbot/mq/base.py\n@@ -36,7 +36,9 @@\n         # we only wait if the check callback return true\n         if not check:\n             res = yield d\n-        yield buildCompleteConsumer.stopConsuming\n+        else:\n+            res = None\n+        yield buildCompleteConsumer.stopConsuming()\n         defer.returnValue(res)\n", "issue": "UnboundLocalError in mq/base.py on master shutdown\nHello,\r\n\r\nWe're using buildbot in multi-master mode and got this stacktrace on one of the master when shutting it down:\r\n```\r\n2017-07-17 12:33:29+0000 [-] Waiting for 1 build(s) to finish\r\n2017-07-17 12:33:29+0000 [-] Builder <Builder 'u'sql-monitor-bitbucket_scality_ring-monitor_ring_frequent-prod-frontend-0'' at 140555339856784> has 1 builds running\r\n2017-07-17 12:33:29+0000 [-] Not shutting down, there are 1 builds running\r\n2017-07-17 12:33:29+0000 [-] Trying shutdown sequence again\r\n2017-07-17 12:33:30+0000 [-] <Build sql-monitor-bitbucket_scality_ring-monitor_ring_frequent-prod-frontend-0 number:32108L results:exception>: stopping build: Master Shutdown 5\r\n2017-07-17 12:33:30+0000 [-] Unhandled error in Deferred:\r\n2017-07-17 12:33:30+0000 [-] Unhandled Error\r\nTraceback (most recent call last):\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py\", line 1299, in _inlineCallbacks\r\nresult = g.send(result)\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/process/botmaster.py\", line 105, in cleanShutdown\r\nl.append(build.waitUntilFinished())\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/process/build.py\", line 687, in waitUntilFinished\r\nlambda: self.finished)\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py\", line 1445, in unwindGenerator\r\nreturn _inlineCallbacks(None, gen, Deferred())\r\n\u2014 <exception caught here> \u2014\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py\", line 1299, in _inlineCallbacks\r\nresult = g.send(result)\r\nFile \"/root/bitbucket/scality/ring/venv/local/lib/python2.7/site-packages/buildbot/mq/base.py\", line 40, in waitUntilEvent\r\ndefer.returnValue(res)\r\nexceptions.UnboundLocalError: local variable 'res' referenced before assignment\r\n```\r\nLooking at the code at the end of `waitUntilEvent()`:\r\n```\r\n        if not check:\r\n            res = yield d\r\n        yield buildCompleteConsumer.stopConsuming\r\n        defer.returnValue(res)\r\n```\r\n\r\nIf the check returned false, we try to return a value (`res`) that was never defined.\n", "before_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import print_function\n\nfrom twisted.internet import defer\nfrom twisted.python import failure\nfrom twisted.python import log\n\nfrom buildbot.util import service\n\n\nclass MQBase(service.AsyncService):\n    name = 'mq-implementation'\n\n    @defer.inlineCallbacks\n    def waitUntilEvent(self, filter, check_callback):\n        d = defer.Deferred()\n        buildCompleteConsumer = yield self.startConsuming(\n            lambda key, value: d.callback((key, value)),\n            filter)\n        check = yield check_callback()\n        # we only wait if the check callback return true\n        if not check:\n            res = yield d\n        yield buildCompleteConsumer.stopConsuming\n        defer.returnValue(res)\n\n\nclass QueueRef(object):\n\n    __slots__ = ['callback']\n\n    def __init__(self, callback):\n        self.callback = callback\n\n    def invoke(self, routing_key, data):\n        if not self.callback:\n            return\n\n        try:\n            x = self.callback(routing_key, data)\n        except Exception:\n            log.err(failure.Failure(), 'while invoking %r' % (self.callback,))\n            return\n        if isinstance(x, defer.Deferred):\n            x.addErrback(log.err, 'while invoking %r' % (self.callback,))\n\n    def stopConsuming(self):\n        # subclasses should set self.callback to None in this method\n        raise NotImplementedError\n", "path": "master/buildbot/mq/base.py"}], "after_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import print_function\n\nfrom twisted.internet import defer\nfrom twisted.python import failure\nfrom twisted.python import log\n\nfrom buildbot.util import service\n\n\nclass MQBase(service.AsyncService):\n    name = 'mq-implementation'\n\n    @defer.inlineCallbacks\n    def waitUntilEvent(self, filter, check_callback):\n        d = defer.Deferred()\n        buildCompleteConsumer = yield self.startConsuming(\n            lambda key, value: d.callback((key, value)),\n            filter)\n        check = yield check_callback()\n        # we only wait if the check callback return true\n        if not check:\n            res = yield d\n        else:\n            res = None\n        yield buildCompleteConsumer.stopConsuming()\n        defer.returnValue(res)\n\n\nclass QueueRef(object):\n\n    __slots__ = ['callback']\n\n    def __init__(self, callback):\n        self.callback = callback\n\n    def invoke(self, routing_key, data):\n        if not self.callback:\n            return\n\n        try:\n            x = self.callback(routing_key, data)\n        except Exception:\n            log.err(failure.Failure(), 'while invoking %r' % (self.callback,))\n            return\n        if isinstance(x, defer.Deferred):\n            x.addErrback(log.err, 'while invoking %r' % (self.callback,))\n\n    def stopConsuming(self):\n        # subclasses should set self.callback to None in this method\n        raise NotImplementedError\n", "path": "master/buildbot/mq/base.py"}]}