From bb382678ab76bb7cf9543de32ed1a96119ebae18 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 11 Sep 2020 06:14:32 +0000 Subject: [FIX] core: remove callbacks from queue before invocation The callbacks system is not re-entrant: because we were only clearing the callbacks after having executed them all, if one of the post-commit callbacks commits then all the callbacks will get re-executed (including the one which commits). Which at best can lead to odd effects & data corruption and at worst crashing the software because we're overflowing the stack (or maybe the other way around, hard-crashing might be a better idea than unexpectedly calling the same functions multiple times). By popping the callbacks before executing them, we ensure that each one will only get called once (unless it's explicitely re-pushed on the stack). closes odoo/odoo#57509 X-original-commit: 4257be4d771605ecd972bd5b04cb9c0f1163b455 Signed-off-by: Xavier Morel (xmo) --- odoo/tools/misc.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'odoo/tools') diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py index 5173e046467..4ecdb6015ef 100644 --- a/odoo/tools/misc.py +++ b/odoo/tools/misc.py @@ -1133,7 +1133,7 @@ class Callbacks: __slots__ = ['_funcs', 'data'] def __init__(self): - self._funcs = [] + self._funcs = collections.deque() self.data = {} def add(self, func): @@ -1141,8 +1141,10 @@ class Callbacks: self._funcs.append(func) def run(self): - """ Call all the functions (in addition order), then clear. """ - for func in self._funcs: + """ Call all the functions (in addition order), then clear associated data. + """ + while self._funcs: + func = self._funcs.popleft() func() self.clear() -- cgit v1.2.3