* extended the jpeg_error_mgr structure to hold the jmp_buf that we need

in the critical error handler. In the high level function, the jmp_buf is
  now allocated on the stack and placed in the "cinfo->err" structure. This
  should make the mechanism thread-safe. Unfortunately, we don't use the
  original libjpeg anymore as is, but this seems to be frozen code since a
  few years anyways. If you have any better suggestions, please don't
  hesitate to mention them! :-)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2008-01-16 15:52:36 +00:00
parent dbc936ac13
commit b91634cbea
4 changed files with 31 additions and 17 deletions
+14 -12
View File
@@ -85,8 +85,10 @@ translation_format outputFormats[] = {
// Main functions of translator :)
static status_t Copy(BPositionIO *in, BPositionIO *out);
static status_t Compress(BPositionIO *in, BPositionIO *out);
static status_t Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension);
static status_t Compress(BPositionIO *in, BPositionIO *out,
const jmp_buf* longJumpBuffer);
static status_t Decompress(BPositionIO *in, BPositionIO *out,
BMessage* ioExtension, const jmp_buf* longJumpBuffer);
static status_t Error(j_common_ptr cinfo, status_t error = B_ERROR);
@@ -1101,9 +1103,6 @@ Identify(BPositionIO *inSource, const translation_format *inFormat,
return B_OK;
}
static jmp_buf sLongJumpBuffer;
jmp_buf* gLongJumpBuffer = &sLongJumpBuffer;
/*! Arguably the most important method in the add-on */
status_t
Translate(BPositionIO *inSource, const translator_info *inInfo,
@@ -1120,7 +1119,8 @@ Translate(BPositionIO *inSource, const translator_info *inInfo,
// this place. If this happens, it is as if the setjmp() call is called
// a second time, but this time the return value will be 1. The first
// invokation will return 0.
int jmpRet = setjmp(sLongJumpBuffer);
jmp_buf longJumpBuffer;
int jmpRet = setjmp(longJumpBuffer);
if (jmpRet == 1)
return B_ERROR;
@@ -1130,10 +1130,11 @@ Translate(BPositionIO *inSource, const translator_info *inInfo,
return Copy(inSource, outDestination);
} else if (inInfo->type == B_TRANSLATOR_BITMAP
&& outType == JPEG_FORMAT) {
return Compress(inSource, outDestination);
return Compress(inSource, outDestination, &longJumpBuffer);
} else if (inInfo->type == JPEG_FORMAT
&& outType == B_TRANSLATOR_BITMAP) {
return Decompress(inSource, outDestination, ioExtension);
return Decompress(inSource, outDestination, ioExtension,
&longJumpBuffer);
}
} catch (...) {
fprintf(stderr, "libjpeg encoutered a critical error "
@@ -1180,7 +1181,7 @@ Copy(BPositionIO *in, BPositionIO *out)
/*! Encode into the native format */
static status_t
Compress(BPositionIO *in, BPositionIO *out)
Compress(BPositionIO *in, BPositionIO *out, const jmp_buf* longJumpBuffer)
{
// Load Settings
jpeg_settings settings;
@@ -1298,7 +1299,7 @@ Compress(BPositionIO *in, BPositionIO *out)
// Set basic things needed for jpeg writing
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = be_jpeg_std_error(&jerr, &settings);
cinfo.err = be_jpeg_std_error(&jerr, &settings, longJumpBuffer);
jpeg_create_compress(&cinfo);
be_jpeg_stdio_dest(&cinfo, out);
@@ -1393,7 +1394,8 @@ Compress(BPositionIO *in, BPositionIO *out)
/*! Decode the native format */
static status_t
Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension,
const jmp_buf* longJumpBuffer)
{
// Load Settings
jpeg_settings settings;
@@ -1402,7 +1404,7 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
// Set basic things needed for jpeg reading
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = be_jpeg_std_error(&jerr, &settings);
cinfo.err = be_jpeg_std_error(&jerr, &settings, longJumpBuffer);
jpeg_create_decompress(&cinfo);
be_jpeg_stdio_src(&cinfo, in);
@@ -213,8 +213,8 @@ EXTERN(void) be_jpeg_stdio_dest(j_compress_ptr cinfo, BPositionIO *outfile); //
// modified to use settings
// (so user can decide to show dialog-boxes or not)
//---------------------------------------------------
EXTERN(struct jpeg_error_mgr *) be_jpeg_std_error (struct jpeg_error_mgr * err, jpeg_settings * settings); // from "be_jerror.cpp"
extern jmp_buf* gLongJumpBuffer;
EXTERN(struct jpeg_error_mgr *) be_jpeg_std_error (struct jpeg_error_mgr * err,
jpeg_settings * settings, const jmp_buf* longJumpBuffer);
// implemented in "be_jerror.cpp"
#endif // _JPEGTRANSLATOR_H_
+10 -2
View File
@@ -69,10 +69,14 @@ be_error_exit (j_common_ptr cinfo)
fprintf(stderr, "JPEG Library Error: %s\n", buffer);
jmp_buf longJumpBuffer;
memcpy(&longJumpBuffer, &(cinfo->err->long_jump_buffer), sizeof(jmp_buf));
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
longjmp(*gLongJumpBuffer, 0);
// jump back directly to the high level function's "breakpoint"
longjmp(longJumpBuffer, 0);
}
@@ -87,6 +91,8 @@ be_output_message (j_common_ptr cinfo)
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
cinfo->err->num_warnings++;
/* If it's compressing or decompressing and user turned messages on */
if (!cinfo->is_decompressor || cinfo->err->ShowReadWarnings) {
/* show warning message */
@@ -103,7 +109,8 @@ be_output_message (j_common_ptr cinfo)
*/
GLOBAL(struct jpeg_error_mgr *)
be_jpeg_std_error (struct jpeg_error_mgr * err, jpeg_settings *settings)
be_jpeg_std_error (struct jpeg_error_mgr * err, jpeg_settings *settings,
const jmp_buf* longJumpBuffer)
{
jpeg_std_error(err);
@@ -111,6 +118,7 @@ be_jpeg_std_error (struct jpeg_error_mgr * err, jpeg_settings *settings)
err->output_message = be_output_message;
err->ShowReadWarnings = settings->ShowReadWarningBox;
memcpy(&(err->long_jump_buffer), longJumpBuffer, sizeof(jmp_buf));
return err;
}
@@ -25,6 +25,8 @@
#endif
#include "jmorecfg.h" /* seldom changed options */
#include <setjmp.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -713,6 +715,8 @@ struct jpeg_error_mgr {
const char * const * addon_message_table; /* Non-library errors */
int first_addon_message; /* code for first string in addon table */
int last_addon_message; /* code for last string in addon table */
jmp_buf long_jump_buffer;
};