[gegl] buffer: fix race condition when disconnecting cache during trimming



commit b628f459d5924517524b8776a1698ad2c989e404
Author: Ell <ell_se yahoo com>
Date:   Thu Jan 3 13:57:39 2019 -0500

    buffer: fix race condition when disconnecting cache during trimming
    
    Since commit 26583900327bf4cff3c8e9461d918889a103b317, we no longer
    hold the global cache mutex throughout cache trimming, which
    introduces a race condition when the currently-trimmed cache is
    being disconnected in another thread, since we rely on the global
    cache mutex for serialization.  Fix this, by acquiring the local
    cache tile-storage mutex, in addition to the global cache mutex,
    when disconnecting a cache.
    
    Additionally, use one of the cache's fields to indicate that the
    cache is being disconnected before acquiring any of the mutexes, so
    that the trimming thread can quickly release them in response,
    instead of keeping trimming the cache.

 gegl/buffer/gegl-tile-handler-cache.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
---
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index b7f9d75d5..4a13895c4 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -323,6 +323,10 @@ gegl_tile_handler_cache_find_oldest_cache (GeglTileHandlerCache *prev_cache)
       if (! time)
         continue;
 
+      /* the cache is being disconnected */
+      if (! cache->link.data)
+        continue;
+
       if (time == stamp)
         {
           oldest_cache = cache;
@@ -624,6 +628,10 @@ gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
           break;
         }
 
+      /* the cache is being disconnected */
+      if (! cache->link.data)
+        link = NULL;
+
       if (! link)
         continue;
 
@@ -947,11 +955,15 @@ gegl_tile_handler_cache_disconnect (GeglTileHandlerCache *cache)
   /* leave the global cache queue */
   if (cache->link.data)
     {
+      cache->link.data = NULL;
+
+      g_rec_mutex_lock (&cache->tile_storage->mutex);
+
       g_mutex_lock (&mutex);
       g_queue_unlink (&cache_queue, &cache->link);
       g_mutex_unlock (&mutex);
 
-      cache->link.data = NULL;
+      g_rec_mutex_unlock (&cache->tile_storage->mutex);
     }
 }
 


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