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:38:11 +0100
commit0940c18905ede976d576150f235e378fe8c4c8b5 (patch)
treed273eef518f2b80e9168038de8045d1c4d187e6a
parentffa2e9a0a763f8a284925edf52022e966c57fce3 (diff)
downloadranger-0940c18905ede976d576150f235e378fe8c4c8b5.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/signal_dispatcher.py26
2 files changed, 22 insertions, 6 deletions
diff --git a/ranger/core/environment.py b/ranger/core/environment.py
index 8d4c60df..417e36c0 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/signal_dispatcher.py b/ranger/ext/signal_dispatcher.py
index 3f407bff..5d80590a 100644
--- a/ranger/ext/signal_dispatcher.py
+++ b/ranger/ext/signal_dispatcher.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