diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index df691cbf1c..169dad96d7 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -172,8 +172,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 @@ -182,6 +180,8 @@ llvm_release_context(JitContext *context) if (proc_exit_inprogress) return; + llvm_enter_fatal_on_oom(); + if (llvm_context->module) { LLVMDisposeModule(llvm_context->module); @@ -885,6 +885,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 26bc828875..daefb3e1fd 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 a8ba5a4fac..3560715e32 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -84,6 +84,7 @@ extern LLVMValueRef AttributeTemplate; 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);