diff --git a/salt/netapi/rest_tornado/saltnado.py b/salt/netapi/rest_tornado/saltnado.py index 6c6a46fa5a..94b5e23edf 100644 --- a/salt/netapi/rest_tornado/saltnado.py +++ b/salt/netapi/rest_tornado/saltnado.py @@ -267,7 +267,8 @@ class EventListener(object): # request_obj -> list of (tag, future) self.request_map = defaultdict(list) - self.timeout_map = {} # map of future -> timeout_callback + # map of future -> timeout_callback + self.timeout_map = {} self.stream = zmqstream.ZMQStream(self.event.sub, io_loop=tornado.ioloop.IOLoop.current()) @@ -280,7 +281,14 @@ class EventListener(object): if request not in self.request_map: return for tag, future in self.request_map[request]: + # timeout the future self._timeout_future(tag, future) + # remove the timeout + if future in self.timeout_map: + tornado.ioloop.IOLoop.current().remove_timeout(self.timeout_map[future]) + del self.timeout_map[future] + + del self.request_map[request] def get_event(self, request, @@ -291,6 +299,13 @@ class EventListener(object): ''' Get an event (async of course) return a future that will get it later ''' + # if the request finished, no reason to allow event fetching, since we + # can't send back to the client + if request._finished: + future = Future() + future.set_exception(TimeoutException()) + return future + future = Future() if callback is not None: def handle_future(future): diff --git a/tests/integration/netapi/rest_tornado/test_app.py b/tests/integration/netapi/rest_tornado/test_app.py index a23d3e9c19..ff1f880fb1 100644 --- a/tests/integration/netapi/rest_tornado/test_app.py +++ b/tests/integration/netapi/rest_tornado/test_app.py @@ -581,6 +581,7 @@ class TestWebhookSaltAPIHandler(SaltnadoTestCase): self.assertIn('headers', event['data']) self.assertEqual(event['data']['post'], {'foo': 'bar'}) # get an event future + self._finished = False # TODO: remove after some cleanup of the event listener event = self.application.event_listener.get_event(self, tag='salt/netapi/hook', callback=verify_event,