[FIX] fields.float: avoid non-deterministic side-effects on other cursors

In 5efac22043 and
1cf5723835 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
This commit is contained in:
Olivier Dony 2015-09-15 19:10:23 +02:00
parent a139d81c46
commit 2b1cdd551f
1 changed files with 2 additions and 13 deletions

View File

@ -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()