[f-spot/stable-0.6] Don't segfault on shutdown in ImageLoaderThread.



commit a0de2ac6269d43a73940be0a69dc137985f060d4
Author: Ruben Vermeersch <ruben savanne be>
Date:   Tue Jun 22 22:48:34 2010 +0200

    Don't segfault on shutdown in ImageLoaderThread.
    
    Backported fix for https://bugzilla.gnome.org/show_bug.cgi?id=621597
    Requested here: https://bugzilla.gnome.org/show_bug.cgi?id=621823

 src/Core/App.cs          |    2 +-
 src/ImageLoaderThread.cs |   45 ++++++++++++++++++++++++++++++++-------------
 2 files changed, 33 insertions(+), 14 deletions(-)
---
diff --git a/src/Core/App.cs b/src/Core/App.cs
index c2207df..d0a26a9 100644
--- a/src/Core/App.cs
+++ b/src/Core/App.cs
@@ -340,7 +340,7 @@ namespace FSpot
 				Log.Information ("Exiting...");
 				Banshee.Kernel.Scheduler.Dispose ();
 				Database.Dispose ();
-				ImageLoaderThread.Cleanup ();
+				ImageLoaderThread.CleanAll ();
 				Gtk.Application.Quit ();
 				System.Environment.Exit (0);
 			}
diff --git a/src/ImageLoaderThread.cs b/src/ImageLoaderThread.cs
index 148c7da..cc340cf 100644
--- a/src/ImageLoaderThread.cs
+++ b/src/ImageLoaderThread.cs
@@ -46,10 +46,10 @@ public class ImageLoaderThread {
 
 
 	// Private members.
+    static List<ImageLoaderThread> instances = new List<ImageLoaderThread> ();
 
 	/* The thread used to handle the requests.  */
 	private Thread worker_thread;
-	private static ArrayList all_worker_threads = new ArrayList ();
 
 	/* The request queue; it's shared between the threads so it
 	   needs to be locked prior to access.  */
@@ -76,6 +76,7 @@ public class ImageLoaderThread {
 	   already or not.  */
 	private bool pending_notify_notified;
 
+	volatile bool should_cancel = false;
 
 	// Public API.
 
@@ -91,10 +92,17 @@ public class ImageLoaderThread {
 		
 		pending_notify = new ThreadNotify (new Gtk.ReadyEvent (HandleProcessedRequests));
 
+        instances.Add (this);
+	}
+
+    void StartWorker ()
+    {
+        if (worker_thread != null)
+            return;
+
+		should_cancel = false;
 		worker_thread = new Thread (new ThreadStart (WorkerThread));
 		worker_thread.Start ();
-
-		all_worker_threads.Add (worker_thread);
 	}
 
 	int block_count;
@@ -112,17 +120,23 @@ public class ImageLoaderThread {
 		}
 	}
 
-	// FIXME?
-	static public void Cleanup ()
+	public void Cleanup ()
 	{
-		foreach (Thread t in all_worker_threads)
-			t.Abort ();
+		should_cancel = true;
+		if (worker_thread != null) {
+			lock (queue) { 
+				Monitor.Pulse (queue); 
+			}
+			worker_thread.Join ();
+		}
+		worker_thread = null;
 	}
 
-	public void Request (Uri uri, int order)
-	{
-		Request (uri, order, 0, 0);
-	}
+    public static void CleanAll ()
+    {
+        foreach (var thread in instances)
+            thread.Cleanup ();
+    }
 
 	public virtual void Request (Uri uri, int order, int width, int height)
 	{
@@ -172,6 +186,8 @@ public class ImageLoaderThread {
 
 	private bool InsertRequest (Uri uri, int order, int width, int height)
 	{
+        StartWorker ();
+
 		/* Check if this is the same as the request currently being processed.  */
 		lock(processed_requests) {
 			if (current_request != null && current_request.uri == uri)
@@ -205,7 +221,7 @@ public class ImageLoaderThread {
 	private void WorkerThread ()
 	{
 		try {
-			while (true) {
+			while (!should_cancel) {
 				lock (processed_requests) {
 					if (current_request != null) {
 						processed_requests.Enqueue (current_request);
@@ -221,8 +237,11 @@ public class ImageLoaderThread {
 	
 				lock (queue) {
 					
-					while (queue.Count == 0 || block_count > 0)
+					while ((queue.Count == 0 || block_count > 0) && !should_cancel)
 						Monitor.Wait (queue);
+
+					if (should_cancel)
+						return;
 					
 					int pos = queue.Count - 1;
 	



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]