Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/docs/reference/c/fitz/error.md @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/docs/reference/c/fitz/error.md Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,71 @@ +# Errors + +MuPDF uses a `setjmp` based exception handling system. This is encapsulated by +the use of three macros: `fz_try`, `fz_always`, and `fz_catch`. When an error +is raised by `fz_throw`, or re-raised by `fz_rethrow`, execution will jump to +the enclosing always/catch block. + +All functions you call should be guarded by a `fz_try` block to catch the +errors, or the program will call `exit()` on errors. You don't want that. + +The `fz_always` block is optional. It is typically used to free memory or +release resources unconditionally, in both the case when the execution of the +try block succeeds, and when an error occurs. + + fz_try(ctx) { + // Do stuff that may throw an exception. + } + fz_always(ctx) { + // This (optional) block is always executed. + } + fz_catch(ctx) { + // This block is only executed when recovering from an exception. + } + + +Since the `fz_try` macro is based on `setjmp`, the same conditions that apply +to local variables in the presence of `setjmp` apply. Any locals written to +inside the try block may be restored to their pre-try state when an error +occurs. We provide a `fz_var()` macro to guard against this. + +In the following example, if we don't guard `buf` with `fz_var`, then when an +error occurs the `buf` local variable might have be reset to its pre-try value +(`NULL`) and we would leak the memory. + + char *buf = NULL; + + fz_var(buf); + + fz_try(ctx) { + buf = fz_malloc(ctx, 100); + // Do stuff with buf that may throw an exception. + } + fz_always(ctx) { + fz_free(ctx, buf); + } + fz_catch(ctx) { + fz_rethrow(ctx); + } + +Carefully note that you should **never** return from within a `fz_try` or +`fz_always block`! Doing so will unbalance the exception stack, and things will +go catastrophically wrong. Instead, it is possible to break out of the `fz_try` +and `fz_always` block by using a break statement if you want to exit the block +early without throwing an exception. + +Throwing a new exception can be done with `fz_throw`. Passing an exception +along after having cleaned up in the `fz_catch` block can be done with +`fz_rethrow`. `fz_throw` takes a `printf`-like formatting string. + + enum { + FZ_ERROR_SYSTEM, // fatal out of memory or syscall error + FZ_ERROR_LIBRARY, // unclassified error from third-party library + FZ_ERROR_ARGUMENT, // invalid or out-of-range arguments to functions + FZ_ERROR_LIMIT, // failed because of resource or other hard limits + FZ_ERROR_UNSUPPORTED, // tried to use an unsupported feature + FZ_ERROR_FORMAT, // syntax or format errors that are unrecoverable + FZ_ERROR_SYNTAX, // syntax errors that should be diagnosed and ignored + }; + + void fz_throw(fz_context *ctx, int error_code, const char *fmt, ...); + void fz_rethrow(fz_context *ctx);
