# Buggy code
def job_not_running(self, jid, tgt, tgt_type, minions, is_finished):
    """
    Return a future which will complete once jid (passed in) is no longer
    running on tgt
    """
    ping_pub_data = yield self.saltclients["local"](
        tgt, "saltutil.find_job", [jid], tgt_type=tgt_type
    )
    ping_tag = tagify([ping_pub_data["jid"], "ret"], "job")

    minion_running = False
    while True:
        try:
            event = self.application.event_listener.get_event(
                self, tag=ping_tag, timeout=self.application.opts["gather_job_timeout"]
            )
            f = yield Any([event, is_finished])
            # When finished entire routine, cleanup other futures and return result
            if f is is_finished:
                if not event.done():
                    event.set_result(None)
                raise tornado.gen.Return(True)
            event = f.result()
        except TimeoutException:
            if not minion_running:
                raise tornado.gen.Return(True)
            else:
                ping_pub_data = yield self.saltclients["local"](
                    tgt, "saltutil.find_job", [jid], tgt_type=tgt_type
                )
                ping_tag = tagify([ping_pub_data["jid"], "ret"], "job")
                minion_running = False
                continue

        # Minions can return, we want to see if the job is running...
        if event["data"].get("return", {}) == {}:
            continue
        if event["data"]["id"] not in minions:
            minions[event["data"]["id"]] = False
        minion_running = True


# Traceback (TypeError)
2018-09-07 19:06:22,631 [tornado.application:1495][ERROR   ][998] Uncaught exception POST /run (127.0.0.1)
HTTPServerRequest(protocol='http', host='localhost:8000', method='POST', uri='/run', version='HTTP/1.1', remote_ip='127.0.0.1', headers={'Host': 'localhost:8000', 'Content-Type': 'application/json', 'Content-Length': '125', 'Accept': 'application/x-yaml', 'User-Agent': 'curl/7.29.0'})
Traceback (most recent call last):
File "/usr/lib64/python2.7/site-packages/tornado/web.py", line 1368, in _stack_context_handle_exception
raise_exc_info((type, value, traceback))
File "/usr/lib64/python2.7/site-packages/tornado/stack_context.py", line 313, in wrapped
ret = fn(*args, **kwargs)
File "/usr/lib64/python2.7/site-packages/tornado/gen.py", line 770, in <lambda>
IOLoop.current().call_later(duration, lambda: f.set_result(None))
File "/usr/lib64/python2.7/site-packages/tornado/concurrent.py", line 253, in set_result
self._set_done()
File "/usr/lib64/python2.7/site-packages/tornado/concurrent.py", line 297, in _set_done
for cb in self._callbacks:
TypeError: 'NoneType' object is not iterable

# Fixed code
def job_not_running(self, jid, tgt, tgt_type, minions, is_finished):
    """
    Return a future which will complete once jid (passed in) is no longer
    running on tgt
    """
    ping_pub_data = yield self.saltclients["local"](
        tgt, "saltutil.find_job", [jid], tgt_type=tgt_type
    )
    ping_tag = tagify([ping_pub_data["jid"], "ret"], "job")

    minion_running = False
    while True:
        try:
            event = self.application.event_listener.get_event(
                self, tag=ping_tag, timeout=self.application.opts["gather_job_timeout"]
            )
            event = yield event
        except TimeoutException:
            if not event.done():
                event.set_result(None)

            if not minion_running:
                raise tornado.gen.Return(True)
            else:
                ping_pub_data = yield self.saltclients["local"](
                    tgt, "saltutil.find_job", [jid], tgt_type=tgt_type
                )
                ping_tag = tagify([ping_pub_data["jid"], "ret"], "job")
                minion_running = False
                continue

        # Minions can return, we want to see if the job is running...
        if event["data"].get("return", {}) == {}:
            continue
        if event["data"]["id"] not in minions:
            minions[event["data"]["id"]] = False
        minion_running = True