[shotwell] Don't call non-threadsafe code from thread in thumbnailer: Bug #742102



commit c3c3c0b97e3b806e123b25c1fb694c828b2c8ab2
Author: Jim Nelson <jim yorba org>
Date:   Tue Dec 30 14:20:10 2014 -0800

    Don't call non-threadsafe code from thread in thumbnailer: Bug #742102

 src/ThumbnailCache.vala |   62 +++++++++++++++++++++++++---------------------
 1 files changed, 34 insertions(+), 28 deletions(-)
---
diff --git a/src/ThumbnailCache.vala b/src/ThumbnailCache.vala
index c24087c..439c28e 100644
--- a/src/ThumbnailCache.vala
+++ b/src/ThumbnailCache.vala
@@ -86,6 +86,7 @@ public class ThumbnailCache : Object {
         public Gdk.Pixbuf scaled = null;
         public Error err = null;
         public bool fetched = false;
+        public bool replace = false;
         
         public AsyncFetchJob(ThumbnailCache cache, string thumbnail_name,
             ThumbnailSource source, Gdk.Pixbuf? prefetched, Dimensions dim,
@@ -131,38 +132,33 @@ public class ThumbnailCache : Object {
                 // scale if specified
                 scaled = dim.has_area() ? resize_pixbuf(unscaled, dim, interp) : unscaled;
             } catch (Error err) {
-                // Is the problem that the thumbnail couldn't be read? If so, it's recoverable;
-                // we'll just create it and leave this.err as null if creation works.
                 if (err is FileError) {
                     try {
-                        Photo photo = source as Photo;
-                        Video video = source as Video;
-
-                        if (photo != null) {
-                            unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true));
-                            photo.notify_altered(new Alteration("image","thumbnail"));
-                            return;
-                        }
-
-                        if (video != null) {
-                            unscaled = video.create_thumbnail(dim.width);
-                            scaled = resize_pixbuf(unscaled, dim, interp);
-                            cache.save_thumbnail(cache.get_source_cached_file(source),
-                                unscaled, source);
-                            replace(source, cache.size, unscaled);
-                            return;
-                        }
-
-                    } catch (Error e) {
-                        // Creating the thumbnail failed; tell the rest of the app.
-                        this.err = e;
-                        return;
+                        generate_thumbnail();
+                    } catch (Error generr) {
+                        // save thumbnail generation error, not original, for processing in callback
+                        err = generr;
                     }
+                } else {
+                    // save error for processing in callback
+                    this.err = err;
                 }
-
-                // ...the original error wasn't from reading the file, but something else;
-                // tell the rest of the app.
-                this.err = err;
+            }
+        }
+        
+        private void generate_thumbnail() throws Error {
+            Photo? photo = source as Photo;
+            if (photo != null) {
+                unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true));
+            } else {
+                Video? video = source as Video;
+                if (video != null)
+                    unscaled = video.create_thumbnail(dim.width);
+            }
+            
+            if (unscaled != null) {
+                scaled = resize_pixbuf(unscaled, dim, interp);
+                replace = true;
             }
         }
     }
@@ -420,6 +416,16 @@ public class ThumbnailCache : Object {
     private static void async_fetch_completion_callback(BackgroundJob background_job) {
         AsyncFetchJob job = (AsyncFetchJob) background_job;
         
+        // Is the problem that the thumbnail couldn't be read? If so, it's recoverable;
+        // we'll just create it and leave this.err as null if creation works.
+        if (job.replace && job.unscaled != null) {
+            try {
+                replace(job.source, job.cache.size, job.unscaled);
+            } catch (Error err) {
+                job.err = err;
+            }
+        }
+        
         if (job.unscaled != null) {
             if (job.fetched) {
                 // only store in cache if fetched, not pre-fetched


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