emacs-devel
[Top][All Lists]
Advanced

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

Re: trunk r113947: * image.c: Fix animation cache signature memory leak.


From: Paul Eggert
Subject: Re: trunk r113947: * image.c: Fix animation cache signature memory leak.
Date: Mon, 19 Aug 2013 12:46:11 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130803 Thunderbird/17.0.8

Lars Magne Ingebrigtsen wrote:

> calling the cache pruning function now and then would probably
> be a good idea?  I'm not sure where it should be called from, though.
> The idle timer?

Sounds plausible, though I'm not an idle-timer expert.

> if that can be tuned, then it would probably be nice to get rid of
> the extra memory.

Sure, that's easy.  Something like this, perhaps?  What images do
you use to test this sort of thing on?

=== modified file 'src/ChangeLog'
--- src/ChangeLog       2013-08-19 17:56:58 +0000
+++ src/ChangeLog       2013-08-19 19:33:19 +0000
@@ -1,3 +1,19 @@
+2013-08-19  Paul Eggert  <address@hidden>
+
+       * image.c: Shrink memory needed for animation cache.
+       (SIGNATURE_DIGESTSIZE): New constant.
+       (struct animation_cache): Make 'signature' a fixed size array of bytes.
+       (imagemagick_create_cache): Copy the signature.  This saves
+       several KB of memory that ImageMagick wastes per signature.
+       Don't bother updating the update_time, as the caller does that now.
+       (imagemagick_prune_animation_cache): Don't destroy the signature, as
+       it's a fixed size struct member now.
+       (imagemagick_get_animation_cache): Always destroy the signature,
+       as it's now imagemagick_create_cache's responsibility to copy it.
+       Avoid duplicate calls to strcmp and to imagemagick_create_cache,
+       and use memcmp rather than strcmp.
+       eassert that ImageMagick returns a signature of the specified length.
+
 2013-08-19  Lars Magne Ingebrigtsen  <address@hidden>
 
        * image.c (imagemagick_get_animation_cache): Don't segfault on

=== modified file 'src/image.c'
--- src/image.c 2013-08-19 17:56:58 +0000
+++ src/image.c 2013-08-19 19:33:19 +0000
@@ -7876,13 +7876,17 @@
    separate from the image cache, because the images may be scaled
    before display. */
 
+/* Size of ImageMagick image signatures, in bytes.  It's SHA-256 as a
+   hex string, so it's 256 bits represented via 4 bits per byte.  */
+enum { SIGNATURE_DIGESTSIZE = 256 / 4 };
+
 struct animation_cache
 {
-  char *signature;
   MagickWand *wand;
   int index;
   EMACS_TIME update_time;
   struct animation_cache *next;
+  char signature[SIGNATURE_DIGESTSIZE];
 };
 
 static struct animation_cache *animation_cache = NULL;
@@ -7891,11 +7895,10 @@
 imagemagick_create_cache (char *signature)
 {
   struct animation_cache *cache = xmalloc (sizeof *cache);
-  cache->signature = signature;
   cache->wand = 0;
   cache->index = 0;
   cache->next = 0;
-  cache->update_time = current_emacs_time ();
+  memcpy (cache->signature, signature, SIGNATURE_DIGESTSIZE);
   return cache;
 }
 
@@ -7914,7 +7917,6 @@
        pcache = &cache->next;
       else
        {
-         DestroyString (cache->signature);
          if (cache->wand)
            DestroyMagickWand (cache->wand);
          *pcache = cache->next;
@@ -7928,24 +7930,22 @@
 {
   char *signature = MagickGetImageSignature (wand);
   struct animation_cache *cache;
+  struct animation_cache **pcache = &animation_cache;
 
+  eassert (strlen (signature) == SIGNATURE_DIGESTSIZE);
   imagemagick_prune_animation_cache ();
-  cache = animation_cache;
-
-  if (! cache)
-    {
-      animation_cache = imagemagick_create_cache (signature);
-      return animation_cache;
-    }
-
-  while (strcmp (signature, cache->signature) &&
-        cache->next)
-    cache = cache->next;
-
-  if (strcmp (signature, cache->signature))
-    {
-      cache->next = imagemagick_create_cache (signature);
-      return cache->next;
+
+  while (1)
+    {
+      cache = *pcache;
+      if (! cache)
+       {
+          *pcache = cache = imagemagick_create_cache (signature);
+          break;
+        }
+      if (memcmp (signature, cache->signature, SIGNATURE_DIGESTSIZE) == 0)
+       break;
+      pcache = &cache->next;
     }
 
   DestroyString (signature);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]