diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index 75b2d260b8..b1954c4764 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -181,8 +181,6 @@ llvm_release_context(JitContext *context) { LLVMJitContext *llvm_context = (LLVMJitContext *) context; - llvm_enter_fatal_on_oom(); - /* * When this backend is exiting, don't clean up LLVM. As an error might * have occurred from within LLVM, we do not want to risk reentering. All @@ -191,6 +189,8 @@ llvm_release_context(JitContext *context) if (proc_exit_inprogress) return; + llvm_enter_fatal_on_oom(); + if (llvm_context->module) { LLVMDisposeModule(llvm_context->module); @@ -849,6 +849,20 @@ llvm_session_initialize(void) static void llvm_shutdown(int code, Datum arg) { + /* + * If llvm_shutdown() is reached while in a fatal-on-oom section an error + * has occurred in the middle of LLVM code. It is not safe to call back + * into LLVM (which is why a FATAL error was thrown). + * + * We do need to shutdown LLVM in other shutdown cases, otherwise + * e.g. profiling data won't be written out. + */ + if (llvm_in_fatal_on_oom()) + { + Assert(proc_exit_inprogress); + return; + } + #if LLVM_VERSION_MAJOR > 11 { if (llvm_opt3_orc) diff --git a/src/backend/jit/llvm/llvmjit_error.cpp b/src/backend/jit/llvm/llvmjit_error.cpp index baabfc4eb4..904ea586c4 100644 --- a/src/backend/jit/llvm/llvmjit_error.cpp +++ b/src/backend/jit/llvm/llvmjit_error.cpp @@ -83,6 +83,16 @@ llvm_leave_fatal_on_oom(void) } } +/* + * Are we currently in an fatal-on-oom section? Useful to skip cleanup in case + * of errors. + */ +bool +llvm_in_fatal_on_oom(void) +{ + return fatal_new_handler_depth > 0; +} + /* * Reset fatal error handling. This should only be called in error recovery * loops like PostgresMain()'s. diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 4beb013a1e..c111ed802a 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -90,6 +90,7 @@ extern LLVMValueRef FuncExecAggInitGroup; extern void llvm_enter_fatal_on_oom(void); extern void llvm_leave_fatal_on_oom(void); +extern bool llvm_in_fatal_on_oom(void); extern void llvm_reset_after_error(void); extern void llvm_assert_in_fatal_section(void);