From 9b83f1144024c98cad6ece752b7e625bfec608f2 Mon Sep 17 00:00:00 2001 From: hut Date: Tue, 30 Mar 2010 19:15:41 +0200 Subject: fixed memory leak --- ranger/core/actions.py | 2 +- ranger/core/environment.py | 12 ++++----- ranger/core/fm.py | 3 ++- ranger/fsobject/directory.py | 49 +++++++++++++++++++++++-------------- ranger/fsobject/fsobject.py | 9 +++++-- ranger/gui/widgets/browsercolumn.py | 5 ++-- ranger/shared/settings.py | 8 +++--- 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 6f2b8606..6eef3d41 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -305,7 +305,7 @@ class Actions(EnvironmentAware, SettingsAware): def reset(self): """Reset the filemanager, clearing the directory buffer""" old_path = self.env.cwd.path - self.env.directories = {} + self.env.garbage_collect(-1) self.enter_dir(old_path) def toggle_boolean_option(self, string): diff --git a/ranger/core/environment.py b/ranger/core/environment.py index 8799229c..cdca9782 100644 --- a/ranger/core/environment.py +++ b/ranger/core/environment.py @@ -100,14 +100,14 @@ class Environment(SettingsAware): except KeyError: return directory - def garbage_collect(self): + def garbage_collect(self, age): """Delete unused directory objects""" - from ranger.fsobject.fsobject import FileSystemObject - for key in tuple(self.directories.keys()): + for key in tuple(self.directories): value = self.directories[key] - if isinstance(value, FileSystemObject): - if value.is_older_than(1200) and not value in self.pathway: - del self.directories[key] + if value.is_older_than(age): # and not value in self.pathway: + del self.directories[key] + if value.is_directory: + value.files = None def get_selection(self): if self.cwd: diff --git a/ranger/core/fm.py b/ranger/core/fm.py index aef10150..de22a86c 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -32,6 +32,7 @@ from ranger.fsobject import Loader CTRL_C = 3 TICKS_BEFORE_COLLECTING_GARBAGE = 100 +TIME_BEFORE_FILE_BECOMES_GARBAGE = 1200 class FM(Actions, SignalDispatcher): input_blocked = False @@ -141,7 +142,7 @@ class FM(Actions, SignalDispatcher): gc_tick += 1 if gc_tick > TICKS_BEFORE_COLLECTING_GARBAGE: gc_tick = 0 - env.garbage_collect() + env.garbage_collect(TIME_BEFORE_FILE_BECOMES_GARBAGE) except KeyboardInterrupt: # this only happens in --debug mode. By default, interrupts diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py index 3ceaaa79..eb031ffe 100644 --- a/ranger/fsobject/directory.py +++ b/ranger/fsobject/directory.py @@ -58,10 +58,9 @@ class Directory(FileSystemObject, Accumulator, SettingsAware): last_update_time = -1 load_content_mtime = -1 + order_outdated = False + content_outdated = False old_show_hidden = None - old_sort_directories_first = None - old_sort_reverse = None - old_sort = None old_filter = None old_hidden_filter = None @@ -85,12 +84,32 @@ class Directory(FileSystemObject, Accumulator, SettingsAware): # to find out if something has changed: self.old_show_hidden = self.settings.show_hidden - self.old_sort_directories_first = self.settings.sort_directories_first - self.old_sort = self.settings.sort self.old_filter = self.filter self.old_hidden_filter = self.settings.hidden_filter - self.old_sort_reverse = self.settings.sort_reverse - self.old_sort_case_insensitive = self.settings.sort_case_insensitive + + self.handlers = [] + lst = ('sort_directories_first', 'sort', 'sort_reverse', + 'sort_case_insensitive') + for opt in lst: + self.handlers.append(self.settings.signal_bind('setopt.' + opt, + self.request_resort, weak=True)) + + lst = ('filter', 'hidden_filter', 'show_hidden') + for opt in lst: + self.handlers.append(self.settings.signal_bind('setopt.' + opt, + self.request_reload, weak=True)) + + def __del__(self): + log("freeing {0}".format(self)) + for handler in self.handlers: + self.settings.signal_unbind(handler) + + def request_resort(self): + self.order_outdated = True + + def request_reload(self): +# log("request a reload for {0}".format(self)) + self.content_outdated = True def get_list(self): return self.files @@ -295,12 +314,8 @@ class Directory(FileSystemObject, Accumulator, SettingsAware): def sort_if_outdated(self): """Sort the containing files if they are outdated""" - if self.old_sort_directories_first != \ - self.settings.sort_directories_first \ - or self.old_sort != self.settings.sort \ - or self.old_sort_reverse != self.settings.sort_reverse \ - or self.old_sort_case_insensitive != \ - self.settings.sort_case_insensitive: + if self.order_outdated: + self.order_outdated = False self.sort() return True return False @@ -375,12 +390,8 @@ class Directory(FileSystemObject, Accumulator, SettingsAware): if self.load_content_once(*a, **k): return True - if self.old_show_hidden != self.settings.show_hidden or \ - self.old_filter != self.filter or \ - self.old_hidden_filter != self.settings.hidden_filter: - self.old_filter = self.filter - self.old_hidden_filter = self.settings.hidden_filter - self.old_show_hidden = self.settings.show_hidden + if self.content_outdated: + self.content_outdated = False self.load_content(*a, **k) return True diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py index 4278c3e8..6933b18d 100644 --- a/ranger/fsobject/fsobject.py +++ b/ranger/fsobject/fsobject.py @@ -17,6 +17,8 @@ CONTAINER_EXTENSIONS = 'rar zip tar gz bz bz2 tgz 7z iso cab'.split() DOCUMENT_EXTENSIONS = 'pdf doc ppt odt'.split() DOCUMENT_BASENAMES = 'README TODO LICENSE COPYING INSTALL'.split() +import time +from ranger import log from . import T_FILE, T_DIRECTORY, T_UNKNOWN, T_NONEXISTANT, BAD_INFO from ranger.shared import MimeTypeAware, FileManagerAware from ranger.ext.shell_escape import shell_escape @@ -81,6 +83,9 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): self.set_mimetype() self.use() + def __repr__(self): + return "<{0} {1}>".format(self.__class__.__name__, self.path) + @property def shell_escaped_basename(self): if self._shell_escaped_basename is None: @@ -109,12 +114,12 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): def use(self): """mark the filesystem-object as used at the current time""" - import time self.last_used = time.time() def is_older_than(self, seconds): """returns whether this object wasn't use()d in the last n seconds""" - import time + if seconds < 0: + return True return self.last_used + seconds < time.time() def set_mimetype(self): diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 7de716c7..6f414cf6 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -133,6 +133,9 @@ class BrowserColumn(Pager): self.need_redraw = True self.old_dir = self.target + if self.target: # don't garbage collect this directory please + self.target.use() + if self.target and self.target.is_directory \ and (self.level <= 0 or self.settings.preview_directories): if self.target.pointed_obj != self.old_cf: @@ -202,8 +205,6 @@ class BrowserColumn(Pager): base_color = ['in_browser'] - self.target.use() - self.win.move(0, 0) if not self.target.content_loaded: diff --git a/ranger/shared/settings.py b/ranger/shared/settings.py index 9c005e29..55259218 100644 --- a/ranger/shared/settings.py +++ b/ranger/shared/settings.py @@ -63,10 +63,10 @@ class SettingObject(SignalDispatcher): assert self._check_type(name, value) kws = dict(setting=name, value=value, previous=self._settings[name]) - self.signal_bind('core.setting.'+name, + self.signal_bind('setopt.'+name, self._raw_set_with_signal, priority=0.2) - self.signal_emit('core.setting', **kws) - self.signal_emit('core.setting.'+name, **kws) + self.signal_emit('setopt', **kws) + self.signal_emit('setopt.'+name, **kws) def __getattr__(self, name): assert name in ALLOWED_SETTINGS or name in self._settings, \ @@ -117,7 +117,7 @@ class SettingsAware(object): settings = SettingObject() from ranger.gui.colorscheme import _colorscheme_name_to_class - settings.signal_bind('core.setting.colorscheme', + settings.signal_bind('setopt.colorscheme', _colorscheme_name_to_class, priority=1) from ranger.defaults import options as default_options -- cgit 1.4.1-2-gfad0