avoid re-entrancy into giflib using the mutex API
authorTony Cook <tony@develop-help.com>
Sat, 25 Aug 2012 03:03:58 +0000 (13:03 +1000)
committerTony Cook <tony@develop-help.com>
Sat, 25 Aug 2012 03:03:58 +0000 (13:03 +1000)
GIF/GIF.pm
GIF/GIF.xs
GIF/imgif.c
GIF/imgif.h

index db78872..5d92f7a 100644 (file)
@@ -4,7 +4,7 @@ use Imager;
 use vars qw($VERSION @ISA);
 
 BEGIN {
-  $VERSION = "0.84";
+  $VERSION = "0.85";
 
   require XSLoader;
   XSLoader::load('Imager::File::GIF', $VERSION);
index 75687b8..7641b8c 100644 (file)
@@ -147,3 +147,4 @@ i_readgif_multi_wiol(ig)
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
        PERL_INITIALIZE_IMAGER_PERL_CALLBACKS;
+       i_init_gif();
index 78f6554..3302d48 100644 (file)
@@ -69,6 +69,12 @@ static int
   InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
 
 
+static i_mutex_t mutex;
+
+void
+i_init_gif(void) {
+  mutex = i_mutex_new();
+}
 
 static
 void
@@ -846,17 +852,25 @@ static int io_glue_read_cb(GifFileType *gft, GifByteType *buf, int length);
 i_img **
 i_readgif_multi_wiol(io_glue *ig, int *count) {
   GifFileType *GifFile;
-  
+  i_img **result;
+
+  i_mutex_lock(mutex);
+
   i_clear_error();
   
   if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) {
     gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_multi_wiol: Unable to open callback datasource.\n"));
+    i_mutex_unlock(mutex);
     return NULL;
   }
     
-  return i_readgif_multi_low(GifFile, count, -1);
+  result = i_readgif_multi_low(GifFile, count, -1);
+
+  i_mutex_unlock(mutex);
+
+  return result;
 }
 
 static int
@@ -869,6 +883,9 @@ io_glue_read_cb(GifFileType *gft, GifByteType *buf, int length) {
 i_img *
 i_readgif_wiol(io_glue *ig, int **color_table, int *colors) {
   GifFileType *GifFile;
+  i_img *result;
+
+  i_mutex_lock(mutex);
 
   i_clear_error();
 
@@ -876,10 +893,15 @@ i_readgif_wiol(io_glue *ig, int **color_table, int *colors) {
     gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
+    i_mutex_unlock(mutex);
     return NULL;
   }
     
-  return i_readgif_low(GifFile, color_table, colors);
+  result = i_readgif_low(GifFile, color_table, colors);
+
+  i_mutex_unlock(mutex);
+
+  return result;
 }
 
 /*
@@ -924,6 +946,7 @@ Returns NULL if the page isn't found.
 i_img *
 i_readgif_single_wiol(io_glue *ig, int page) {
   GifFileType *GifFile;
+  i_img *result;
 
   i_clear_error();
   if (page < 0) {
@@ -931,14 +954,21 @@ i_readgif_single_wiol(io_glue *ig, int page) {
     return NULL;
   }
 
+  i_mutex_lock(mutex);
+
   if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) {
     gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
+    i_mutex_unlock(mutex);
     return NULL;
   }
     
-  return i_readgif_single_low(GifFile, page);
+  result = i_readgif_single_low(GifFile, page);
+
+  i_mutex_unlock(mutex);
+
+  return result;
 }
 
 /*
@@ -1797,6 +1827,8 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs,
   GifFileType *GifFile;
   int result;
 
+  i_mutex_lock(mutex);
+
   i_clear_error();
 
   gif_set_version(quant, imgs, count);
@@ -1805,11 +1837,14 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs,
     gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_writegif_wiol: Unable to open callback datasource.\n"));
+    i_mutex_unlock(mutex);
     return 0;
   }
   
   result = i_writegif_low(quant, GifFile, imgs, count);
   
+  i_mutex_unlock(mutex);
+
   if (i_io_close(ig))
     return 0;
   
@@ -1945,6 +1980,8 @@ EGifSetGifVersion().  See L<gif_set_version> for an explanation.
 
 Arnar M. Hrafnkelsson, addi@umich.edu
 
+Tony Cook <tonyc@cpan.org>
+
 =head1 SEE ALSO
 
 perl(1), Imager(3)
index ca92af5..9a92e8c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "imext.h"
 
+void i_init_gif(void);
 double i_giflib_version(void);
 i_img *i_readgif_wiol(io_glue *ig, int **colour_table, int *colours);
 i_img *i_readgif_single_wiol(io_glue *ig, int page);