[gegl] Bug 795597 - gegl crashes for a race ...
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Bug 795597 - gegl crashes for a race ...
- Date: Fri, 27 Apr 2018 14:34:10 +0000 (UTC)
commit 60ae8750710f308d857fcc3cc0d6c04657e90f5b
Author: Ell <ell_se yahoo com>
Date: Fri Apr 27 10:26:13 2018 -0400
Bug 795597 - gegl crashes for a race ...
... between disposing a GeglTileHandlerChain and storing a tile
(trimming the cache)
Add gegl_tile_handler_cache_{connect,disconnect}(), which add/
remove the cache to the global cache queue. Cache handlers are
connected upon construction, and disconnected upon destruction.
While a cache is disconnected, it may not be accessed while
trimming unrelated caches.
In GeglTileStore, disconnect the cache before destroying the
storage, so that other threads trimming an unrelated cache
concurrently may not interfere with destruction.
gegl/buffer/gegl-tile-handler-cache.c | 36 +++++++++++++++++++++++++++-----
gegl/buffer/gegl-tile-handler-cache.h | 3 ++
gegl/buffer/gegl-tile-storage.c | 15 +++++++++++++
3 files changed, 48 insertions(+), 6 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 6914fe1..cf76668 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -116,9 +116,7 @@ gegl_tile_handler_cache_init (GeglTileHandlerCache *cache)
g_queue_init (&cache->queue);
gegl_tile_cache_init ();
- g_mutex_lock (&mutex);
- g_queue_push_tail_link (&cache_queue, &cache->link);
- g_mutex_unlock (&mutex);
+ gegl_tile_handler_cache_connect (cache);
}
static void
@@ -184,9 +182,7 @@ gegl_tile_handler_cache_dispose (GObject *object)
{
GeglTileHandlerCache *cache = GEGL_TILE_HANDLER_CACHE (object);
- g_mutex_lock (&mutex);
- g_queue_unlink (&cache_queue, &cache->link);
- g_mutex_unlock (&mutex);
+ gegl_tile_handler_cache_disconnect (cache);
gegl_tile_handler_cache_reinit (cache);
@@ -750,6 +746,34 @@ gegl_tile_handler_cache_new (void)
return g_object_new (GEGL_TYPE_TILE_HANDLER_CACHE, NULL);
}
+void
+gegl_tile_handler_cache_connect (GeglTileHandlerCache *cache)
+{
+ /* join the global cache queue */
+ if (! cache->link.data)
+ {
+ cache->link.data = cache;
+
+ g_mutex_lock (&mutex);
+ g_queue_push_tail_link (&cache_queue, &cache->link);
+ g_mutex_unlock (&mutex);
+ }
+}
+
+void
+gegl_tile_handler_cache_disconnect (GeglTileHandlerCache *cache)
+{
+ /* leave the global cache queue */
+ if (cache->link.data)
+ {
+ g_mutex_lock (&mutex);
+ g_queue_unlink (&cache_queue, &cache->link);
+ g_mutex_unlock (&mutex);
+
+ cache->link.data = NULL;
+ }
+}
+
gsize
gegl_tile_handler_cache_get_total (void)
{
diff --git a/gegl/buffer/gegl-tile-handler-cache.h b/gegl/buffer/gegl-tile-handler-cache.h
index 094d716..ade3267 100644
--- a/gegl/buffer/gegl-tile-handler-cache.h
+++ b/gegl/buffer/gegl-tile-handler-cache.h
@@ -56,6 +56,9 @@ GType gegl_tile_handler_cache_get_type (void) G_GNUC_CONST
GeglTileHandler * gegl_tile_handler_cache_new (void);
+void gegl_tile_handler_cache_connect (GeglTileHandlerCache *cache);
+void gegl_tile_handler_cache_disconnect (GeglTileHandlerCache *cache);
+
void gegl_tile_handler_cache_insert (GeglTileHandlerCache *cache,
GeglTile *tile,
gint x,
diff --git a/gegl/buffer/gegl-tile-storage.c b/gegl/buffer/gegl-tile-storage.c
index 4a3c239..30a5ee3 100644
--- a/gegl/buffer/gegl-tile-storage.c
+++ b/gegl/buffer/gegl-tile-storage.c
@@ -120,6 +120,20 @@ gegl_tile_storage_remove_handler (GeglTileStorage *tile_storage,
}
static void
+gegl_tile_storage_dispose (GObject *object)
+{
+ GeglTileStorage *self = GEGL_TILE_STORAGE (object);
+
+ /* disconnect the cache before destruction, to avoid a race condition with
+ * other threads trimming the global cache through an unrelated cache
+ * handler. see bug #795597.
+ */
+ gegl_tile_handler_cache_disconnect (self->cache);
+
+ (*G_OBJECT_CLASS (parent_class)->dispose)(object);
+}
+
+static void
gegl_tile_storage_finalize (GObject *object)
{
GeglTileStorage *self = GEGL_TILE_STORAGE (object);
@@ -135,6 +149,7 @@ gegl_tile_storage_class_init (GeglTileStorageClass *class)
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
+ gobject_class->dispose = gegl_tile_storage_dispose;
gobject_class->finalize = gegl_tile_storage_finalize;
gegl_tile_storage_signals[CHANGED] =
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]