Skip to content

Commit

Permalink
avoid re-entrancy into libtiff using the mutex api
Browse files Browse the repository at this point in the history
  • Loading branch information
tonycoz committed Nov 12, 2012
1 parent bcf8804 commit c3994bc
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 2 deletions.
2 changes: 1 addition & 1 deletion TIFF/TIFF.pm
Expand Up @@ -4,7 +4,7 @@ use Imager;
use vars qw($VERSION @ISA);

BEGIN {
$VERSION = "0.84";
$VERSION = "0.85";

require XSLoader;
XSLoader::load('Imager::File::TIFF', $VERSION);
Expand Down
1 change: 1 addition & 0 deletions TIFF/TIFF.xs
Expand Up @@ -143,3 +143,4 @@ i_tiff_has_compression(name)

BOOT:
PERL_INITIALIZE_IMAGER_CALLBACKS;
i_tiff_init();
42 changes: 41 additions & 1 deletion TIFF/imtiff.c
Expand Up @@ -266,6 +266,13 @@ static void warn_handler(char const *module, char const *fmt, va_list ap) {

#endif

static i_mutex_t mutex;

void
i_tiff_init(void) {
mutex = i_mutex_new();
}

static int save_tiff_tags(TIFF *tif, i_img *im);

static void
Expand Down Expand Up @@ -621,6 +628,8 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
int current_page;
tiffio_context_t ctx;

i_mutex_lock(mutex);

i_clear_error();
old_handler = TIFFSetErrorHandler(error_handler);
#ifdef USE_EXT_WARN_HANDLER
Expand Down Expand Up @@ -658,6 +667,7 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
TIFFSetWarningHandlerExt(old_ext_warn_handler);
#endif
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return NULL;
}

Expand All @@ -672,6 +682,7 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
#endif
TIFFClose(tif);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return NULL;
}
}
Expand All @@ -686,6 +697,7 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
#endif
TIFFClose(tif);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);

return im;
}
Expand All @@ -709,6 +721,8 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
int result_alloc = 0;
tiffio_context_t ctx;

i_mutex_lock(mutex);

i_clear_error();
old_handler = TIFFSetErrorHandler(error_handler);
#ifdef USE_EXT_WARN_HANDLER
Expand Down Expand Up @@ -747,6 +761,7 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
TIFFSetWarningHandlerExt(old_ext_warn_handler);
#endif
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return NULL;
}

Expand Down Expand Up @@ -781,6 +796,7 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
#endif
TIFFClose(tif);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);

return results;
}
Expand Down Expand Up @@ -1446,6 +1462,8 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
int i;
tiffio_context_t ctx;

i_mutex_lock(mutex);

old_handler = TIFFSetErrorHandler(error_handler);

i_clear_error();
Expand All @@ -1472,6 +1490,7 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
i_push_error(0, "Could not create TIFF object");
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

Expand All @@ -1480,6 +1499,7 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

Expand All @@ -1488,6 +1508,7 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}
}
Expand All @@ -1496,6 +1517,8 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
(void) TIFFClose(tif);
tiffio_context_final(&ctx);

i_mutex_unlock(mutex);

if (i_io_close(ig))
return 0;

Expand All @@ -1522,6 +1545,8 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
TIFFErrorHandler old_handler;
tiffio_context_t ctx;

i_mutex_lock(mutex);

old_handler = TIFFSetErrorHandler(error_handler);

i_clear_error();
Expand All @@ -1548,6 +1573,7 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
i_push_error(0, "Could not create TIFF object");
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

Expand All @@ -1556,6 +1582,7 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

Expand All @@ -1564,6 +1591,7 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}
}
Expand All @@ -1572,6 +1600,8 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);

i_mutex_unlock(mutex);

if (i_io_close(ig))
return 0;

Expand All @@ -1594,6 +1624,8 @@ i_writetiff_wiol(i_img *img, io_glue *ig) {
TIFFErrorHandler old_handler;
tiffio_context_t ctx;

i_mutex_lock(mutex);

old_handler = TIFFSetErrorHandler(error_handler);

i_clear_error();
Expand All @@ -1619,19 +1651,22 @@ i_writetiff_wiol(i_img *img, io_glue *ig) {
i_push_error(0, "Could not create TIFF object");
tiffio_context_final(&ctx);
TIFFSetErrorHandler(old_handler);
i_mutex_unlock(mutex);
return 0;
}

if (!i_writetiff_low(tif, img)) {
TIFFClose(tif);
tiffio_context_final(&ctx);
TIFFSetErrorHandler(old_handler);
i_mutex_unlock(mutex);
return 0;
}

(void) TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);

if (i_io_close(ig))
return 0;
Expand Down Expand Up @@ -1662,6 +1697,8 @@ i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
TIFFErrorHandler old_handler;
tiffio_context_t ctx;

i_mutex_lock(mutex);

old_handler = TIFFSetErrorHandler(error_handler);

i_clear_error();
Expand All @@ -1687,19 +1724,22 @@ i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
i_push_error(0, "Could not create TIFF object");
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

if (!i_writetiff_low_faxable(tif, im, fine)) {
TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);
return 0;
}

(void) TIFFClose(tif);
TIFFSetErrorHandler(old_handler);
tiffio_context_final(&ctx);
i_mutex_unlock(mutex);

if (i_io_close(ig))
return 0;
Expand Down
1 change: 1 addition & 0 deletions TIFF/imtiff.h
Expand Up @@ -3,6 +3,7 @@

#include "imdatatypes.h"

void i_tiff_init(void);
i_img * i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page);
i_img ** i_readtiff_multi_wiol(io_glue *ig, int *count);
undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
Expand Down
1 change: 1 addition & 0 deletions bench/.gitignore
@@ -0,0 +1 @@
/largish.tif
Binary file added bench/largish.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions bench/tifthread.pl
@@ -0,0 +1,55 @@
#!perl -w
use strict;
use threads;
use Imager;

++$|;
Imager->preload;

# as a TIFF this file is large, build it from largeish.jpg if it
# doesn't exist
unless (-f "bench/largish.tif") {
my $im = Imager->new(file => "bench/largish.jpg")
or die "Cannot read bench/largish.jpg:", Imager->errstr;
$im->write(file => "bench/largish.tif")
or die "Cannot write bench.largish.tif:", $im->errstr;
}

my @tests =
(
[ "bench/largish.tif", "" ],
[ "TIFF/testimg/grey16.tif", "" ],
[ "TIFF/testimg/comp4bad.tif", "(Iolayer): Read error at scanline 120; got 0 bytes, expected 32" ],
);

my @threads;
my $name = "A";
for my $test (@tests) {
push @threads,
threads->create
(
sub {
my ($file, $result, $name) = @_;
for (1 .. 100000) {
print $name;
my $im = Imager->new(file => $file);
if ($result) {
$im and die "Expected error from $file, got image";
Imager->errstr eq $result
or die "Expected error '$result', got '",Imager->errstr, "'"
}
else {
$im or die "Expected image got error '", Imager->errstr, "'";
}
}
return;
},
@$test,
$name
);
++$name;
}

for my $t (@threads) {
$t->join();
}

0 comments on commit c3994bc

Please sign in to comment.