From a95756faac9233a4e831695c2a7cd4f22e4bfac2 Mon Sep 17 00:00:00 2001 From: XavierDo Date: Mon, 18 Feb 2019 16:23:35 +0000 Subject: [PATCH] [FIX] bus: gc event at the end of a polling When making a poll, an event is registered on each channel. Once a notification is sent on a channel, only the events of the notified channel are removed. A pointer to the event is kept in all other channel the user subscribes to until those channel are notified. Since a user usually has many mail.channels but only a few active ones, a new event and a bunch of pointers are created at each poll and never removed. This fix simply remove the pointers to the current event at the end of a poll. closes odoo/odoo#31215 Signed-off-by: Toufik Benjaa (tbe) --- addons/bus/models/bus.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index d5d84fa77d2..9350ea805d1 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -141,7 +141,7 @@ class ImDispatch(object): event = self.Event() for channel in channels: - self.channels.setdefault(hashable(channel), []).append(event) + self.channels.setdefault(hashable(channel), set()).add(event) try: event.wait(timeout=timeout) with registry.cursor() as cr: @@ -150,6 +150,12 @@ class ImDispatch(object): except Exception: # timeout pass + finally: + # gc pointers to event + for channel in channels: + channel_events = self.channels.get(hashable(channel)) + if channel_events and event in channel_events: + channel_events.remove(event) return notifications def loop(self): @@ -170,7 +176,7 @@ class ImDispatch(object): # dispatch to local threads/greenlets events = set() for channel in channels: - events.update(self.channels.pop(hashable(channel), [])) + events.update(self.channels.pop(hashable(channel), set())) for event in events: event.set()