* it was a really bad idea to invoke exit() on critical errors from an add-on

that only loads bitmaps and is supposed to return a status_t error from
  the Translate() function, especially for people using this in mission
  critical applications.
  The requirements on the error handler that is
  to be installed for the jpeg library are not to return to the calling
  function for critical errors. C++ exceptions seem like the
  natural solution to the problem, but unfortunately, they simply don't
  seem to work, possibly because we are inside an add-on. Ingo had the idea
  to use setjmp() and longjmp() to go directly from the error handler back
  to the top level code and this works. I have implemented this from what
  I understand from reading the opengroup spec, but the compiler currently
  issues a warning. Feel free to fix. The desired effects are achieved though, 
  the translator recovers correctly from broken jpg files now.
  Also, I don't know if the translator should somehow "uninstall" the
  breakpoint. Again, feel free to fix or tell me.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23559 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2008-01-16 13:28:28 +00:00
parent 5dda419aeb
commit dbc936ac13
3 changed files with 39 additions and 18 deletions

View File

@ -1101,21 +1101,44 @@ 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,
BMessage *ioExtension, uint32 outType, BPositionIO *outDestination)
{
// If no specific type was requested, convert to the interchange format
if (outType == 0) outType = B_TRANSLATOR_BITMAP;
// What action to take, based on the findings of Identify()
if (outType == inInfo->type) {
return Copy(inSource, outDestination);
} else if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JPEG_FORMAT) {
return Compress(inSource, outDestination);
} else if (inInfo->type == JPEG_FORMAT && outType == B_TRANSLATOR_BITMAP) {
return Decompress(inSource, outDestination, ioExtension);
if (outType == 0)
outType = B_TRANSLATOR_BITMAP;
// Setup a "breakpoint" since throwing exceptions does not seem to work
// at all in an add-on. (?)
// In the be_jerror.cpp we implement a handler for critical library errors
// (be_error_exit()) and there we use the longjmp() function to return to
// 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);
if (jmpRet == 1)
return B_ERROR;
try {
// What action to take, based on the findings of Identify()
if (outType == inInfo->type) {
return Copy(inSource, outDestination);
} else if (inInfo->type == B_TRANSLATOR_BITMAP
&& outType == JPEG_FORMAT) {
return Compress(inSource, outDestination);
} else if (inInfo->type == JPEG_FORMAT
&& outType == B_TRANSLATOR_BITMAP) {
return Decompress(inSource, outDestination, ioExtension);
}
} catch (...) {
fprintf(stderr, "libjpeg encoutered a critical error "
"(caught C++ exception).\n");
return B_ERROR;
}
return B_NO_TRANSLATOR;

View File

@ -42,6 +42,7 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <TranslationKit.h>
#include <TranslatorAddOn.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -214,5 +215,6 @@ EXTERN(void) be_jpeg_stdio_dest(j_compress_ptr cinfo, BPositionIO *outfile); //
//---------------------------------------------------
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;
#endif // _JPEGTRANSLATOR_H_

View File

@ -67,15 +67,12 @@ be_error_exit (j_common_ptr cinfo)
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
#if 0
/* show error message */
(new BAlert("JPEG Library Error", buffer, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
#endif
fprintf(stderr, "JPEG Library Error: %s\n", buffer);
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
exit(B_ERROR);
longjmp(*gLongJumpBuffer, 0);
}
@ -90,12 +87,11 @@ be_output_message (j_common_ptr cinfo)
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
#if 0
/* If it's compressing or decompressing and user turned messages on */
if (!cinfo->is_decompressor || cinfo->err->ShowReadWarnings)
if (!cinfo->is_decompressor || cinfo->err->ShowReadWarnings) {
/* show warning message */
(new BAlert("JPEG Library Warning", buffer, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
#endif
fprintf(stderr, "JPEG Library Warning: %s\n", buffer);
}
}