From 535490a073934a1950989dcb56461dc6db326780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 26 Apr 2018 09:38:47 +0200 Subject: [PATCH] [FIX] web: fix a race condition in web client Here is an interesting scenario, involving the reconciliation tour again (because it is our only tour that does async stuff before changing url): - web client starts normally - tour reconciliation starts, perform an rpc to find some id - web client fetches users default action, it is empty, so clicks on first menu item to load initial action, which is discuss. this will make the web client load the action with datamanager (it should be the action manager's job!). - reconciliation tour rpc completes, it changes the url, this will do a do_action - the load_action rpc from the web client completes, it will then perform a do_action, which will drop the action initiated by the tour - tour fails. The issue here is that the on_menu_action method from the web client is not really safe, from a concurrency point of view: it performs some asynchronous work, and then unilateraly decides to do a doAction. With this commit, we simply add the do_action request to the action manager, which uses internally a "dropprevious" system. This means that it will always use the last action, just as expected. --- addons/web/static/src/js/chrome/web_client.js | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js index e2b3a23d2a6..c4886cd0e89 100644 --- a/addons/web/static/src/js/chrome/web_client.js +++ b/addons/web/static/src/js/chrome/web_client.js @@ -157,27 +157,10 @@ return AbstractWebClient.extend({ }); }, on_menu_action: function(options) { - var self = this; - return this.menu_dm.add(data_manager.load_action(options.action_id)) - .then(function (result) { - return self.action_mutex.exec(function() { - var completed = $.Deferred(); - self.action_manager.doAction(result, { - clear_breadcrumbs: true, - action_menu_id: options.id, - }).fail(function() { - self.menu.open_menu(options.previous_menu_id); - }).always(function() { - completed.resolve(); - }); - setTimeout(function() { - completed.resolve(); - }, 2000); - // We block the menu when clicking on an element until the action has correctly finished - // loading. If something crash, there is a 2 seconds timeout before it's unblocked. - return completed; - }); - }); + this.action_manager.doAction(options.action_id, { + clear_breadcrumbs: true, + action_menu_id: options.id, + }); }, toggle_fullscreen: function(fullscreen) { this._super(fullscreen);