about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2010-11-22 02:06:46 +0100
committerhut <hut@lavabit.com>2010-11-22 02:06:46 +0100
commite3f6f484f0bb516a802f60f6dae89580d47a2217 (patch)
treeb8f6093800e3c10627d193096a6d8a9aa84ecea5
parentfe6e709f4ccff7e0fe8aa8e492b79396012c780c (diff)
downloadranger-e3f6f484f0bb516a802f60f6dae89580d47a2217.tar.gz
ext.signals: fixed memory leak
Signal handlers with dead weak references are only cleaned up
when using signal_emit.  If no signals are emitted, dead signal
handlers will accumulate.  This is avoided by adding the function
signal_garbage_collect() and calling it in env.garbage_collect()
-rw-r--r--ranger/core/environment.py2
-rw-r--r--ranger/ext/signals.py26
2 files changed, 22 insertions, 6 deletions
diff --git a/ranger/core/environment.py b/ranger/core/environment.py
index 8f5cece7..2a72229b 100644
--- a/ranger/core/environment.py
+++ b/ranger/core/environment.py
@@ -128,6 +128,8 @@ class Environment(SettingsAware, SignalDispatcher):
 				del self.directories[key]
 				if value.is_directory:
 					value.files = None
+		self.settings.signal_garbage_collect()
+		self.signal_garbage_collect()
 
 	def get_selection(self):
 		if self.cwd:
diff --git a/ranger/ext/signals.py b/ranger/ext/signals.py
index 3f407bff..5d80590a 100644
--- a/ranger/ext/signals.py
+++ b/ranger/ext/signals.py
@@ -74,6 +74,20 @@ class SignalDispatcher(object):
 			except:
 				pass
 
+	def signal_garbage_collect(self):
+		for handler_list in self._signals.values():
+			i = len(handler_list)
+			while i:
+				i -= 1
+				handler = handler_list[i]
+				try:
+					if isinstance(handler.function, tuple):
+						handler.function[1].__class__
+					else:
+						handler.function.__class__
+				except ReferenceError:
+					del handler_list[i]
+
 	def signal_emit(self, signal_name, **kw):
 		assert isinstance(signal_name, str)
 		if signal_name not in self._signals:
@@ -87,17 +101,17 @@ class SignalDispatcher(object):
 		# propagate
 		for handler in tuple(handlers):
 			if handler.active:
+				if isinstance(handler.function, tuple):
+					fnc = MethodType(*handler.function)
+				else:
+					fnc = handler.function
 				try:
-					if isinstance(handler.function, tuple):
-						fnc = MethodType(*handler.function)
-					else:
-						fnc = handler.function
 					if handler.pass_signal:
 						fnc(signal)
 					else:
 						fnc()
-					if signal.stopped:
-						return False
 				except ReferenceError:
 					handlers.remove(handler)
+				if signal.stopped:
+					return False
 		return True