comparison 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
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 # Errors
2
3 MuPDF uses a `setjmp` based exception handling system. This is encapsulated by
4 the use of three macros: `fz_try`, `fz_always`, and `fz_catch`. When an error
5 is raised by `fz_throw`, or re-raised by `fz_rethrow`, execution will jump to
6 the enclosing always/catch block.
7
8 All functions you call should be guarded by a `fz_try` block to catch the
9 errors, or the program will call `exit()` on errors. You don't want that.
10
11 The `fz_always` block is optional. It is typically used to free memory or
12 release resources unconditionally, in both the case when the execution of the
13 try block succeeds, and when an error occurs.
14
15 fz_try(ctx) {
16 // Do stuff that may throw an exception.
17 }
18 fz_always(ctx) {
19 // This (optional) block is always executed.
20 }
21 fz_catch(ctx) {
22 // This block is only executed when recovering from an exception.
23 }
24
25
26 Since the `fz_try` macro is based on `setjmp`, the same conditions that apply
27 to local variables in the presence of `setjmp` apply. Any locals written to
28 inside the try block may be restored to their pre-try state when an error
29 occurs. We provide a `fz_var()` macro to guard against this.
30
31 In the following example, if we don't guard `buf` with `fz_var`, then when an
32 error occurs the `buf` local variable might have be reset to its pre-try value
33 (`NULL`) and we would leak the memory.
34
35 char *buf = NULL;
36
37 fz_var(buf);
38
39 fz_try(ctx) {
40 buf = fz_malloc(ctx, 100);
41 // Do stuff with buf that may throw an exception.
42 }
43 fz_always(ctx) {
44 fz_free(ctx, buf);
45 }
46 fz_catch(ctx) {
47 fz_rethrow(ctx);
48 }
49
50 Carefully note that you should **never** return from within a `fz_try` or
51 `fz_always block`! Doing so will unbalance the exception stack, and things will
52 go catastrophically wrong. Instead, it is possible to break out of the `fz_try`
53 and `fz_always` block by using a break statement if you want to exit the block
54 early without throwing an exception.
55
56 Throwing a new exception can be done with `fz_throw`. Passing an exception
57 along after having cleaned up in the `fz_catch` block can be done with
58 `fz_rethrow`. `fz_throw` takes a `printf`-like formatting string.
59
60 enum {
61 FZ_ERROR_SYSTEM, // fatal out of memory or syscall error
62 FZ_ERROR_LIBRARY, // unclassified error from third-party library
63 FZ_ERROR_ARGUMENT, // invalid or out-of-range arguments to functions
64 FZ_ERROR_LIMIT, // failed because of resource or other hard limits
65 FZ_ERROR_UNSUPPORTED, // tried to use an unsupported feature
66 FZ_ERROR_FORMAT, // syntax or format errors that are unrecoverable
67 FZ_ERROR_SYNTAX, // syntax errors that should be diagnosed and ignored
68 };
69
70 void fz_throw(fz_context *ctx, int error_code, const char *fmt, ...);
71 void fz_rethrow(fz_context *ctx);