mirror of
https://github.com/evennia/evennia.git
synced 2026-03-23 00:06:30 +01:00
Fix edge case in TaskHandler when un-pickleable callable supplied
This commit is contained in:
parent
cec566be79
commit
bf4af8b208
2 changed files with 27 additions and 26 deletions
|
|
@ -5,6 +5,7 @@ Module containing the task handler for Evennia deferred tasks, persistent or not
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
from twisted.internet import reactor
|
||||
from pickle import PickleError
|
||||
from twisted.internet.task import deferLater
|
||||
from twisted.internet.defer import CancelledError as DefCancelledError
|
||||
from evennia.server.models import ServerConfig
|
||||
|
|
@ -287,18 +288,8 @@ class TaskHandler(object):
|
|||
# Check if callback can be pickled. args and kwargs have been checked
|
||||
safe_callback = None
|
||||
|
||||
try:
|
||||
dbserialize(callback)
|
||||
except (TypeError, AttributeError):
|
||||
raise ValueError(
|
||||
"the specified callback {} cannot be pickled. "
|
||||
"It must be a top-level function in a module or an "
|
||||
"instance method.".format(callback)
|
||||
)
|
||||
else:
|
||||
safe_callback = callback
|
||||
|
||||
self.to_save[task_id] = dbserialize((date, safe_callback, args, kwargs))
|
||||
self.to_save[task_id] = dbserialize((date, callback, args, kwargs))
|
||||
ServerConfig.objects.conf("delayed_tasks", self.to_save)
|
||||
|
||||
def add(self, timedelay, callback, *args, **kwargs):
|
||||
|
|
@ -318,8 +309,8 @@ class TaskHandler(object):
|
|||
any (any): any additional positional arguments to send to the callback
|
||||
*args: positional arguments to pass to callback.
|
||||
**kwargs: keyword arguments to pass to callback.
|
||||
persistent (bool, optional): persist the task (stores it).
|
||||
persistent key and value is removed from kwargs it will
|
||||
- persistent (bool, optional): persist the task (stores it).
|
||||
Persistent key and value is removed from kwargs it will
|
||||
not be passed to callback.
|
||||
|
||||
Returns:
|
||||
|
|
@ -346,11 +337,22 @@ class TaskHandler(object):
|
|||
safe_args = []
|
||||
safe_kwargs = {}
|
||||
|
||||
# an unsaveable callback should immediately abort
|
||||
try:
|
||||
dbserialize(callback)
|
||||
except (TypeError, AttributeError, PickleError):
|
||||
raise ValueError(
|
||||
"the specified callback {} cannot be pickled. "
|
||||
"It must be a top-level function in a module or an "
|
||||
"instance method.".format(callback)
|
||||
)
|
||||
return
|
||||
|
||||
# Check that args and kwargs contain picklable information
|
||||
for arg in args:
|
||||
try:
|
||||
dbserialize(arg)
|
||||
except (TypeError, AttributeError):
|
||||
except (TypeError, AttributeError, PickleError):
|
||||
log_err(
|
||||
"The positional argument {} cannot be "
|
||||
"pickled and will not be present in the arguments "
|
||||
|
|
@ -362,7 +364,7 @@ class TaskHandler(object):
|
|||
for key, value in kwargs.items():
|
||||
try:
|
||||
dbserialize(value)
|
||||
except (TypeError, AttributeError):
|
||||
except (TypeError, AttributeError, PickleError):
|
||||
log_err(
|
||||
"The {} keyword argument {} cannot be "
|
||||
"pickled and will not be present in the arguments "
|
||||
|
|
|
|||
|
|
@ -1030,20 +1030,19 @@ def delay(timedelay, callback, *args, **kwargs):
|
|||
after `timedelay` seconds.
|
||||
args (any, optional): Will be used as arguments to callback
|
||||
Keyword Args:
|
||||
persistent (bool, optional): should make the delay persistent
|
||||
over a reboot or reload
|
||||
persistent (bool, optional): Should make the delay persistent
|
||||
over a reboot or reload. Defaults to False.
|
||||
any (any): Will be used as keyword arguments to callback.
|
||||
|
||||
Returns:
|
||||
deferred (deferred): Will fire with callback after
|
||||
`timedelay` seconds. Note that if `timedelay()` is used in the
|
||||
commandhandler callback chain, the callback chain can be
|
||||
defined directly in the command body and don't need to be
|
||||
specified here.
|
||||
Reference twisted.internet.defer.Deferred
|
||||
if persistent kwarg is truthy:
|
||||
task_id (int): the task's id intended for use with
|
||||
evennia.scripts.taskhandler.TASK_HANDLER's do_task and remove methods.
|
||||
deferred or int: If ``persistent`` kwarg is `False`, return deferred
|
||||
that will fire with callback after `timedelay` seconds. Note that
|
||||
if `timedelay()` is used in the commandhandler callback chain, the
|
||||
callback chain can be defined directly in the command body and
|
||||
don't need to be specified here. Reference twisted.internet.defer.Deferred.
|
||||
If persistent kwarg is set, return the task's ID as an integer. This is
|
||||
intended for use with ``evennia.scripts.taskhandler.TASK_HANDLER``
|
||||
`.do_task` and `.remove` methods.
|
||||
|
||||
Note:
|
||||
The task handler (`evennia.scripts.taskhandler.TASK_HANDLER`) will
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue