summaryrefslogtreecommitdiff
path: root/include/mupdf/fitz/context.h
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-09-25 17:03:04 +0100
committerRobin Watts <robin.watts@artifex.com>2015-09-28 13:28:48 +0100
commiteaa8bfedd2bff50400254f9d4240cccce16614a5 (patch)
treedb618925721a409ef85b895013f63713320391a6 /include/mupdf/fitz/context.h
parentaf69c1326cd2bcc0c7c142abe0d7a374cf099448 (diff)
downloadmupdf-eaa8bfedd2bff50400254f9d4240cccce16614a5.tar.xz
Bug 696115: Fix problem with fz_try/fz_catch with modern gcc's.
Modern gcc's have a compiler (optimiser) bug that can cause values not to be written back to memory when they should. We work around this by using an inline function to force the compiler to behave. Many thanks to Marcos Woehrmann for doing the analysis that lead to this workaround.
Diffstat (limited to 'include/mupdf/fitz/context.h')
-rw-r--r--include/mupdf/fitz/context.h16
1 files changed, 15 insertions, 1 deletions
diff --git a/include/mupdf/fitz/context.h b/include/mupdf/fitz/context.h
index 02bd6eaa..905a82ef 100644
--- a/include/mupdf/fitz/context.h
+++ b/include/mupdf/fitz/context.h
@@ -49,9 +49,18 @@ void fz_var_imp(void *);
attention to the man behind the curtain.
*/
+/*
+ OK, so you looked behind the curtain, and you're wondering why we use
+ an inline function for fz_trying, rather than doing a bare assignment
+ and test. See bug 696115. Various versions of gcc (depressingly,
+ modern ones) cause problems under optimisation whereby the value
+ returned from setjmp is not written correctly. This causes the rest
+ of the try/catch to behave incorrectly. The use of a function call
+ here suffices to solve it.
+*/
#define fz_try(ctx) \
if (fz_push_try(ctx->error) && \
- ((ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0))\
+ fz_trying(ctx->error, fz_setjmp(ctx->error->stack[ctx->error->top].buffer)))\
{ do {
#define fz_always(ctx) \
@@ -68,6 +77,11 @@ void fz_var_imp(void *);
if (ctx->error->stack[ctx->error->top--].code > 1)
int fz_push_try(fz_error_context *ex);
+static inline int fz_trying(fz_error_context *error, int value)
+{
+ error->stack[error->top].code = value;
+ return value == 0;
+}
FZ_NORETURN void fz_throw(fz_context *, int errcode, const char *, ...) __printflike(3, 4);
FZ_NORETURN void fz_rethrow(fz_context *);
FZ_NORETURN void fz_rethrow_message(fz_context *, const char *, ...) __printflike(2, 3);