Remove all timer deadlocks by using idle_add priority for them.
Add util.idle_timeout_add() to register timers with the same priority as idle_add(). Change the IdleTimeout to also use the idle_add() priority. This eliminates the chance of a timer blocking any idle_add from running. Change most timeout_add's to idle_timeout_add. Change the timer in DownloadStatusModel::get_next() back to an idle_add.
This commit is contained in:
parent
d2f34d0d87
commit
e1fc290ef2
|
@ -195,10 +195,7 @@ class DownloadStatusModel(Gtk.ListStore):
|
|||
# as only the main thread is allowed to manipulate the list store.
|
||||
def get_next(self):
|
||||
dqr = DequeueRequest()
|
||||
# this can not be idle_add because update_downloads_list() is called from a higher
|
||||
# priority timeout_add and would spin forever, never calling this.
|
||||
from gi.repository import GLib
|
||||
GLib.timeout_add(0, self.__get_next, dqr)
|
||||
util.idle_add(self.__get_next, dqr)
|
||||
return dqr.dequeue()
|
||||
|
||||
def _work_gen(self):
|
||||
|
|
|
@ -50,6 +50,7 @@ class ProgressIndicator(object):
|
|||
self._initial_message = None
|
||||
self._initial_progress = None
|
||||
self._progress_set = False
|
||||
# use timeout_add, not util.idle_timeout_add, so it updates before Gtk+ redraws the dialog
|
||||
self.source_id = GLib.timeout_add(self.DELAY, self._create_progress)
|
||||
|
||||
self.set_max_ticks(max_ticks)
|
||||
|
@ -111,6 +112,7 @@ class ProgressIndicator(object):
|
|||
self._update_gui()
|
||||
|
||||
# previous self.source_id timeout is removed when this returns False
|
||||
# use timeout_add, not util.idle_timeout_add, so it updates before Gtk+ redraws the dialog
|
||||
self.source_id = GLib.timeout_add(self.INTERVAL, self._update_gui)
|
||||
return False
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ class SearchTree:
|
|||
if self.search_box.get_property('visible'):
|
||||
if self._search_timeout is not None:
|
||||
GLib.source_remove(self._search_timeout)
|
||||
# use timeout_add, not util.idle_timeout_add, so it updates the TreeView before background tasks
|
||||
self._search_timeout = GLib.timeout_add(
|
||||
self.config.ui.gtk.live_search_delay,
|
||||
self.set_search_term, editable.get_chars(0, -1))
|
||||
|
|
|
@ -2431,7 +2431,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
if remaining_seconds > 3600:
|
||||
# timeout an hour early in the event daylight savings changes the clock forward
|
||||
remaining_seconds = remaining_seconds - 3600
|
||||
GLib.timeout_add(remaining_seconds * 1000, self.refresh_episode_dates)
|
||||
util.idle_timeout_add(remaining_seconds * 1000, self.refresh_episode_dates)
|
||||
|
||||
def update_podcast_list_model(self, urls=None, selected=False, select_url=None,
|
||||
sections_changed=False):
|
||||
|
@ -3821,8 +3821,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
interval = 60 * 1000 * self.config.auto.update.frequency
|
||||
logger.debug('Setting up auto update timer with interval %d.',
|
||||
self.config.auto.update.frequency)
|
||||
self._auto_update_timer_source_id = GLib.timeout_add(
|
||||
interval, self._on_auto_update_timer)
|
||||
self._auto_update_timer_source_id = util.idle_timeout_add(interval, self._on_auto_update_timer)
|
||||
|
||||
def _on_auto_update_timer(self):
|
||||
if self.config.check_connection and not util.connection_available():
|
||||
|
|
|
@ -1320,8 +1320,25 @@ def idle_add(func, *args):
|
|||
func(*args)
|
||||
|
||||
|
||||
def idle_timeout_add(milliseconds, func, *args):
|
||||
"""Run a function in the main GUI thread at regular intervals, at idle priority
|
||||
|
||||
PRIORITY_HIGH -100
|
||||
PRIORITY_DEFAULT 0 timeout_add()
|
||||
PRIORITY_HIGH_IDLE 100
|
||||
resizing 110
|
||||
redraw 120
|
||||
PRIORITY_DEFAULT_IDLE 200 idle_add()
|
||||
PRIORITY_LOW 300
|
||||
"""
|
||||
if not gpodder.ui.gtk:
|
||||
raise Exception('util.idle_timeout_add() is only supported by Gtk+')
|
||||
from gi.repository import GLib
|
||||
return GLib.timeout_add(milliseconds, func, *args, priority=GLib.PRIORITY_DEFAULT_IDLE)
|
||||
|
||||
|
||||
class IdleTimeout(object):
|
||||
"""Run a function in the main GUI thread at regular intervals since the last run
|
||||
"""Run a function in the main GUI thread at regular intervals since the last run, at idle priority
|
||||
|
||||
A simple timeout_add() continuously calls the function if it exceeds the interval,
|
||||
which lags the UI and prevents idle_add() calls from happening. This class restarts
|
||||
|
@ -1333,13 +1350,13 @@ class IdleTimeout(object):
|
|||
self.milliseconds = milliseconds
|
||||
self.func = func
|
||||
from gi.repository import GLib
|
||||
self.id = GLib.timeout_add(milliseconds, self._callback, *args)
|
||||
self.id = GLib.timeout_add(milliseconds, self._callback, *args, priority=GLib.PRIORITY_DEFAULT_IDLE)
|
||||
|
||||
def _callback(self, *args):
|
||||
self.cancel()
|
||||
if self.func(*args):
|
||||
from gi.repository import GLib
|
||||
self.id = GLib.timeout_add(self.milliseconds, self._callback, *args)
|
||||
self.id = GLib.timeout_add(self.milliseconds, self._callback, *args, priority=GLib.PRIORITY_DEFAULT_IDLE)
|
||||
|
||||
def cancel(self):
|
||||
if self.id:
|
||||
|
|
Loading…
Reference in New Issue