[FIX] website: use proper env in model methods

Using `request.env` should be reserved for code that lies outside of
model methods (typically: controllers). Model methods have to use the
appropriate `self.env`.

This particular case caused frequent Python-PostgreSQL undetected
deadlocks during installations of website-related modules in 12.0.
One way to reproduce it was to trigger the installation of both
`website` and `website_form` in a single transaction, with neither
pre-installed.

Installing Apps that depend on both would do the job, such as
`website_sale`, provided that GEOIP is available on the system.

In details:
During installation of `website`, new attachments creation would call
get_current_website (see 602807acdf and
4f6ec1cd2a), using the wrong database
cursor: the one from the request instead of the one for the
installation, as provided by `ir.module.module._button_immediate_function`.
This would acquire database locks on `res.country` and `ir.model` in
the wrong transaction, later blocking alterations to `ir.model` in
the installation transaction, e.g. for website_form's
'website_form_access' column.

This combination of events was possible before 12.0, but more difficult
to reproduce as module installations used to happen with a super-user
account, ignoring ACL checks and therefore not locking `ir.model`.
This commit is contained in:
Olivier Dony
2018-10-08 19:29:24 +02:00
parent a362d0eb9f
commit f4041de4ed
+2 -2
View File
@@ -462,7 +462,7 @@ class Website(models.Model):
country = request.session.geoip.get('country_code') if request and request.session.geoip else False
country_id = False
if country:
country_id = request.env['res.country'].search([('code', '=', country)], limit=1).id
country_id = self.env['res.country'].search([('code', '=', country)], limit=1).id
website_id = self._get_current_website_id(domain_name, country_id, fallback=fallback)
return self.browse(website_id)
@@ -644,7 +644,7 @@ class Website(models.Model):
@api.multi
def get_website_pages(self, domain=[], order='name', limit=None):
domain += self.get_current_website().website_domain()
pages = request.env['website.page'].search(domain, order='name', limit=limit)
pages = self.env['website.page'].search(domain, order='name', limit=limit)
return pages
@api.multi