From 2b1cdd551f54bcd7ad15aae1c76ba5d80dd85d95 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 15 Sep 2015 19:10:23 +0200 Subject: [PATCH] [FIX] fields.float: avoid non-deterministic side-effects on other cursors In 5efac22043adc735d9502fb9f6f7466b85916573 and 1cf5723835235c71df140938282420360116f0c5 the computation of the decimal precision of float fields was modified to reuse a random cursor from the request environments. Environment.envs is a WeakSet, subject to unpredictable garbage collections. This could cause hard-to-diagnose problems by executing a SELECT query in a cursor that is supposed to be otherwise idle and untouched. As an example, this could cause a transaction start in a cursor that was just committed/rolled back, and was waiting for another operation to complete. One such case happened semi-randomly during a module installation triggered from the web client, where the request cursor is committed and waiting for the registry initialization done with a different cursor, in the middle of _button_immediate_function() After the registry initialization, the request cursor is used again to determine the next action (ir.actions.todo), and this could cause a TransactionRollbackError if the request cursor was used during the initialization. Using a new cursor every time is much safer, simpler, and will not cause any significant performance hit, because it will usually grab an available connection from the connection pool, rather than create a new one. Fixes opw-649151 --- openerp/osv/fields.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 76aecfe2b84..e836bf370d9 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -56,19 +56,8 @@ from openerp import SUPERUSER_ID, registry @contextmanager def _get_cursor(): # yield a valid cursor from any environment or create a new one if none found - from openerp.api import Environment - from openerp.http import request - try: - request.env # force request's env to be computed - except RuntimeError: - pass # ignore if not in a request - for env in Environment.envs: - if not env.cr.closed: - yield env.cr - break - else: - with registry().cursor() as cr: - yield cr + with registry().cursor() as cr: + yield cr EMPTY_DICT = frozendict()