1 /*-------------------------------------------------------------------------
4 * LLVM error related handling that requires interfacing with C++
6 * Unfortunately neither (re)setting the C++ new handler, nor the LLVM OOM
7 * handler are exposed to C. Therefore this file wraps the necessary code.
9 * Copyright (c) 2016-2025, PostgreSQL Global Development Group
12 * src/backend/jit/llvm/llvmjit_error.cpp
14 *-------------------------------------------------------------------------
22 #include <llvm/Support/ErrorHandling.h>
24 #include "jit/llvmjit.h"
28 static int fatal_new_handler_depth
= 0;
29 static std::new_handler old_new_handler
= NULL
;
31 static void fatal_system_new_handler(void);
32 static void fatal_llvm_new_handler(void *user_data
, const char *reason
, bool gen_crash_diag
);
33 static void fatal_llvm_error_handler(void *user_data
, const char *reason
, bool gen_crash_diag
);
37 * Enter a section in which C++ and LLVM errors are treated as FATAL errors.
39 * This is necessary for LLVM as LLVM's error handling for such cases
40 * (exit()ing, throwing std::bad_alloc() if compiled with exceptions, abort())
41 * isn't compatible with postgres error handling. Thus in sections where LLVM
42 * code, not LLVM generated functions!, is executing, standard new, LLVM OOM
43 * and LLVM fatal errors (some OOM errors masquerade as those) are redirected
44 * to our own error handlers.
46 * These error handlers use FATAL, because there's no reliable way from within
47 * LLVM to throw an error that's guaranteed not to corrupt LLVM's state.
49 * To avoid disturbing extensions using C++ and/or LLVM, these handlers are
50 * unset when not executing LLVM code. There is no need to call
51 * llvm_leave_fatal_on_oom() when ERRORing out, error recovery resets the
52 * handlers in that case.
55 llvm_enter_fatal_on_oom(void)
57 if (fatal_new_handler_depth
== 0)
59 old_new_handler
= std::set_new_handler(fatal_system_new_handler
);
60 llvm::install_bad_alloc_error_handler(fatal_llvm_new_handler
);
61 llvm::install_fatal_error_handler(fatal_llvm_error_handler
);
63 fatal_new_handler_depth
++;
67 * Leave fatal error section started with llvm_enter_fatal_on_oom().
70 llvm_leave_fatal_on_oom(void)
72 fatal_new_handler_depth
--;
73 if (fatal_new_handler_depth
== 0)
75 std::set_new_handler(old_new_handler
);
76 llvm::remove_bad_alloc_error_handler();
77 llvm::remove_fatal_error_handler();
82 * Are we currently in a fatal-on-oom section? Useful to skip cleanup in case
86 llvm_in_fatal_on_oom(void)
88 return fatal_new_handler_depth
> 0;
92 * Reset fatal error handling. This should only be called in error recovery
93 * loops like PostgresMain()'s.
96 llvm_reset_after_error(void)
98 if (fatal_new_handler_depth
!= 0)
100 std::set_new_handler(old_new_handler
);
101 llvm::remove_bad_alloc_error_handler();
102 llvm::remove_fatal_error_handler();
104 fatal_new_handler_depth
= 0;
108 llvm_assert_in_fatal_section(void)
110 Assert(fatal_new_handler_depth
> 0);
114 fatal_system_new_handler(void)
117 (errcode(ERRCODE_OUT_OF_MEMORY
),
118 errmsg("out of memory"),
119 errdetail("while in LLVM")));
123 fatal_llvm_new_handler(void *user_data
,
128 (errcode(ERRCODE_OUT_OF_MEMORY
),
129 errmsg("out of memory"),
130 errdetail("While in LLVM: %s", reason
)));
134 fatal_llvm_error_handler(void *user_data
,
139 (errcode(ERRCODE_OUT_OF_MEMORY
),
140 errmsg("fatal llvm error: %s", reason
)));