[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#57516 X-original-commit: 4257be4d771605ecd972bd5b04cb9c0f1163b455 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
+5
-3
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user