* 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:
parent
5dda419aeb
commit
dbc936ac13
@ -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;
|
||||
|
@ -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_
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user