taskhandler suppress cancel error

Added an errback to handle errors within task handler's deferred instance.
Without this instances of deferred cause a traceback when a deferred is canceled without errback or callback having been called.
This traceback does not end execution, and ultimately would only show to main console.
Reference cancel: https://github.com/twisted/twisted/blob/trunk/src/twisted/internet/defer.py

All evennia unit tests pass.
This commit is contained in:
davewiththenicehat 2021-04-16 10:55:24 -04:00
parent 1a18b247e2
commit c7bf773605
2 changed files with 22 additions and 2 deletions

View file

@ -6,6 +6,7 @@ from datetime import datetime, timedelta
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.task import deferLater from twisted.internet.task import deferLater
from twisted.internet.defer import CancelledError as DefCancelledError
from evennia.server.models import ServerConfig from evennia.server.models import ServerConfig
from evennia.utils.logger import log_err from evennia.utils.logger import log_err
from evennia.utils.dbserialize import dbserialize, dbunserialize from evennia.utils.dbserialize import dbserialize, dbunserialize
@ -13,6 +14,17 @@ from evennia.utils.dbserialize import dbserialize, dbunserialize
TASK_HANDLER = None 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): class TaskHandler(object):
""" """
@ -179,7 +191,9 @@ class TaskHandler(object):
deferLater(self.clock, timedelay, callback, *args, **kwargs) deferLater(self.clock, timedelay, callback, *args, **kwargs)
return task_id 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): def remove(self, task_id):
"""Remove a persistent task without executing it. """Remove a persistent task without executing it.

View file

@ -10,7 +10,7 @@ import mock
from django.test import TestCase from django.test import TestCase
from datetime import datetime from datetime import datetime
from twisted.internet import task, reactor from twisted.internet import task
from evennia.utils.ansi import ANSIString from evennia.utils.ansi import ANSIString
from evennia.utils import utils from evennia.utils import utils
@ -338,3 +338,9 @@ class TestDelay(EvenniaTest):
_TASK_HANDLER.clock.advance(1) # make time pass _TASK_HANDLER.clock.advance(1) # make time pass
self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran') self.assertEqual(self.char1.ndb.dummy_var, 'dummy_func ran')
self.char1.ndb.dummy_var = False 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