diff --git a/evennia/scripts/taskhandler.py b/evennia/scripts/taskhandler.py index 11ac144a94..3273e27e8a 100644 --- a/evennia/scripts/taskhandler.py +++ b/evennia/scripts/taskhandler.py @@ -6,6 +6,7 @@ from datetime import datetime, timedelta from twisted.internet import reactor from twisted.internet.task import deferLater +from twisted.internet.defer import CancelledError as DefCancelledError from evennia.server.models import ServerConfig from evennia.utils.logger import log_err from evennia.utils.dbserialize import dbserialize, dbunserialize @@ -13,6 +14,17 @@ from evennia.utils.dbserialize import dbserialize, dbunserialize TASK_HANDLER = None +def handle_error(*args, **kwargs): + """ + Handle errors withing deferred objects. + """ + for arg in args: + # suppress cancel errors + if arg.type == DefCancelledError: + continue + raise arg + + class TaskHandler(object): """ @@ -179,7 +191,9 @@ class TaskHandler(object): deferLater(self.clock, timedelay, callback, *args, **kwargs) return task_id - return deferLater(self.clock, timedelay, callback, *args, **kwargs) + d = deferLater(self.clock, timedelay, callback, *args, **kwargs) + d.addErrback(handle_error) + return d def remove(self, task_id): """Remove a persistent task without executing it. diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py index ea23601fce..bebea149ce 100644 --- a/evennia/utils/tests/test_utils.py +++ b/evennia/utils/tests/test_utils.py @@ -10,7 +10,7 @@ import mock from django.test import TestCase from datetime import datetime -from twisted.internet import task, reactor +from twisted.internet import task from evennia.utils.ansi import ANSIString from evennia.utils import utils @@ -338,3 +338,9 @@ class TestDelay(EvenniaTest): _TASK_HANDLER.clock.advance(1) # make time pass self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') self.char1.ndb.dummy_var = False + # test canceling a deferral. + deferal_inst = utils.delay(1, dummy_func, self.char1.dbref) + deferal_inst.cancel() + _TASK_HANDLER.clock.advance(1) # make time pass + self.assertEqual(self.char1.ndb.dummy_var, False) + self.char1.ndb.dummy_var = False