# Buggy code
def OnExit(self):
    self.utility.session.notifier.notify(NTFY_CLOSE_TICK, NTFY_CREATE, None, None)

    if self.i2i_server:
        self.i2i_server.stop()

    self._logger.info("main: ONEXIT")
    self.ready = False
    self.done = True

    # write all persistent data to disk
    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Write all persistent data to disk"
    )
    wx.Yield()

    if self.webUI:
        self.webUI.stop()
        self.webUI.delInstance()

    if self.frame:
        self.frame.Destroy()
        self.frame = None

    # Don't checkpoint, interferes with current way of saving Preferences,
    # see Tribler/Main/Dialogs/abcoption.py
    if self.utility:
        # Niels: lets add a max waiting time for this session shutdown.
        session_shutdown_start = time()

        # TODO(emilon): probably more notification callbacks should be remmoved
        # here
        s = self.utility.session
        s.remove_observer(self.sesscb_ntfy_newversion)
        s.remove_observer(self.sesscb_ntfy_corrupt_torrent)
        s.remove_observer(self.sesscb_ntfy_magnet)
        s.remove_observer(self.sesscb_ntfy_torrentfinished)
        s.remove_observer(self.sesscb_ntfy_markingupdates)
        s.remove_observer(self.sesscb_ntfy_moderationupdats)
        s.remove_observer(self.sesscb_ntfy_modificationupdates)
        s.remove_observer(self.sesscb_ntfy_commentupdates)
        s.remove_observer(self.sesscb_ntfy_playlistupdates)
        s.remove_observer(self.sesscb_ntfy_torrentupdates)
        s.remove_observer(self.sesscb_ntfy_myprefupdates)
        s.remove_observer(self.sesscb_ntfy_channelupdates)
        s.remove_observer(self.sesscb_ntfy_channelupdates)
        s.remove_observer(self.sesscb_ntfy_activities)
        s.remove_observer(self.sesscb_ntfy_reachable)

        try:
            self._logger.info("ONEXIT cleaning database")
            self.utility.session.notifier.notify(
                NTFY_CLOSE_TICK, NTFY_INSERT, None, "Cleaning database"
            )
            wx.Yield()
            torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS)
            torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True)
        except:
            print_exc()

        self.utility.session.notifier.notify(
            NTFY_CLOSE_TICK, NTFY_INSERT, None, "Shutdown session"
        )
        wx.Yield()
        self.utility.session.shutdown(hacksessconfcheckpoint=False)

        # Arno, 2012-07-12: Shutdown should be quick
        # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk
        waittime = 60
        while not self.utility.session.has_shutdown():
            diff = time() - session_shutdown_start
            if diff > waittime:
                self._logger.info(
                    "main: ONEXIT NOT Waiting for Session to shutdown, took too long"
                )
                break

            self._logger.info(
                "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds",
                waittime - diff,
            )
            sleep(3)
        self._logger.info("ONEXIT Session is shutdown")

    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Deleting instances"
    )
    self._logger.debug("ONEXIT deleting instances")

    Session.del_instance()
    GUIDBProducer.delInstance()
    DefaultDownloadStartupConfig.delInstance()
    GuiImageManager.delInstance()

    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Exiting now"
    )

    self.utility.session.notifier.notify(NTFY_CLOSE_TICK, NTFY_DELETE, None, None)

    GUIUtility.delInstance()


# Traceback (isError)
Regression

Tribler.Test.Core.Modules.RestApi.test_downloads_endpoint.TestDownloadsEndpoint.test_remove_download_no_remove_data_param (from nosetests)
Failing for the past 1 build (Since Failed#2109 )
Took 4.4 sec.
Error Message

Test raised 1 unhandled Twisted exceptions:
[{'log_namespace': u'log_legacy', 'log_time': 1467938979.639, 'format': '%(log_legacy)s', 'log_system': '-', 'log_legacy': <twisted.logger._stdlib.StringifiableFromEvent object at 0x06D22830>, 'log_level': <LogLevel=critical>, 'system': '-', 'isError': 1, 'failure': <twisted.python.failure.Failure exceptions.AttributeError: 'NoneType' object has no attribute 'add_task'>, 'time': 1467938979.639, 'log_text': 'Unhandled Error\nTraceback (most recent call last):\n  File "C:\\Python27\\lib\\threading.py", line 763, in run\n    self.__target(*self.__args, **self.__kwargs)\n  File "C:\\workspace\\jenkins\\workspace\\GH_Tribler_PR_tests_win32\\tribler\\Tribler\\Core\\Utilities\\twisted_thread.py", line 55, in _reactor_runner\n    reactor.run(installSignalHandlers=False)\n  File "C:\\Python27\\lib\\site-packages\\twisted\\internet\\base.py", line 1194, in run\n    self.mainLoop()\n  File "C:\\Python27\\lib\\site-packages\\twisted\\internet\\base.py", line 1203, in mainLoop\n    self.runUntilCurrent()\n--- <exception caught here> ---\n  File "C:\\Python27\\lib\\site-packages\\twisted\\internet\\base.py", line 825, in runUntilCurrent\n    call.func(*call.args, **call.kw)\n  File "C:\\workspace\\jenkins\\workspace\\GH_Tribler_PR_tests_win32\\tribler\\Tribler\\Core\\Libtorrent\\__init__.py", line 27, in <lambda>\n    lambda_f = lambda a = args, kwa = kwargs: invoke_func(*a, **kwa)\n  File "C:\\workspace\\jenkins\\workspace\\GH_Tribler_PR_tests_win32\\tribler\\Tribler\\Core\\Libtorrent\\__init__.py", line 28, in invoke_func\n    download.session.lm.threadpool.add_task(lambda_f, 1)\nexceptions.AttributeError: \'NoneType\' object has no attribute \'add_task\'\n', 'log_format': u'{log_text}', 'message': (), 'why': None}]

# Fixed code
def OnExit(self):
    self.utility.session.notifier.notify(NTFY_CLOSE_TICK, NTFY_CREATE, None, None)

    blockingCallFromThread(reactor, self.cancel_all_pending_tasks)

    if self.i2i_server:
        self.i2i_server.stop()

    self._logger.info("main: ONEXIT")
    self.ready = False
    self.done = True

    # write all persistent data to disk
    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Write all persistent data to disk"
    )
    wx.Yield()

    if self.webUI:
        self.webUI.stop()
        self.webUI.delInstance()

    if self.frame:
        self.frame.Destroy()
        self.frame = None

    # Don't checkpoint, interferes with current way of saving Preferences,
    # see Tribler/Main/Dialogs/abcoption.py
    if self.utility:
        # Niels: lets add a max waiting time for this session shutdown.
        session_shutdown_start = time()

        # TODO(emilon): probably more notification callbacks should be remmoved
        # here
        s = self.utility.session
        s.remove_observer(self.sesscb_ntfy_newversion)
        s.remove_observer(self.sesscb_ntfy_corrupt_torrent)
        s.remove_observer(self.sesscb_ntfy_magnet)
        s.remove_observer(self.sesscb_ntfy_torrentfinished)
        s.remove_observer(self.sesscb_ntfy_markingupdates)
        s.remove_observer(self.sesscb_ntfy_moderationupdats)
        s.remove_observer(self.sesscb_ntfy_modificationupdates)
        s.remove_observer(self.sesscb_ntfy_commentupdates)
        s.remove_observer(self.sesscb_ntfy_playlistupdates)
        s.remove_observer(self.sesscb_ntfy_torrentupdates)
        s.remove_observer(self.sesscb_ntfy_myprefupdates)
        s.remove_observer(self.sesscb_ntfy_channelupdates)
        s.remove_observer(self.sesscb_ntfy_channelupdates)
        s.remove_observer(self.sesscb_ntfy_activities)
        s.remove_observer(self.sesscb_ntfy_reachable)

        try:
            self._logger.info("ONEXIT cleaning database")
            self.utility.session.notifier.notify(
                NTFY_CLOSE_TICK, NTFY_INSERT, None, "Cleaning database"
            )
            wx.Yield()
            torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS)
            torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True)
        except:
            print_exc()

        self.utility.session.notifier.notify(
            NTFY_CLOSE_TICK, NTFY_INSERT, None, "Shutdown session"
        )
        wx.Yield()
        self.utility.session.shutdown(hacksessconfcheckpoint=False)

        # Arno, 2012-07-12: Shutdown should be quick
        # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk
        waittime = 60
        while not self.utility.session.has_shutdown():
            diff = time() - session_shutdown_start
            if diff > waittime:
                self._logger.info(
                    "main: ONEXIT NOT Waiting for Session to shutdown, took too long"
                )
                break

            self._logger.info(
                "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds",
                waittime - diff,
            )
            sleep(3)
        self._logger.info("ONEXIT Session is shutdown")

    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Deleting instances"
    )
    self._logger.debug("ONEXIT deleting instances")

    Session.del_instance()
    GUIDBProducer.delInstance()
    DefaultDownloadStartupConfig.delInstance()
    GuiImageManager.delInstance()

    self.utility.session.notifier.notify(
        NTFY_CLOSE_TICK, NTFY_INSERT, None, "Exiting now"
    )

    self.utility.session.notifier.notify(NTFY_CLOSE_TICK, NTFY_DELETE, None, None)

    GUIUtility.delInstance()