LCOV - differential code coverage report
Current view: top level - src/backend/jit/llvm - llvmjit_error.cpp (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 81.2 % 32 26 6 26
Current Date: 2023-04-08 17:13:01 Functions: 62.5 % 8 5 3 5
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 81.2 % 32 26 6 26
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 62.5 % 8 5 3 5

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * llvmjit_error.cpp
                                  4                 :  *    LLVM error related handling that requires interfacing with C++
                                  5                 :  *
                                  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.
                                  8                 :  *
                                  9                 :  * Copyright (c) 2016-2023, PostgreSQL Global Development Group
                                 10                 :  *
                                 11                 :  * IDENTIFICATION
                                 12                 :  *    src/backend/jit/llvm/llvmjit_error.cpp
                                 13                 :  *
                                 14                 :  *-------------------------------------------------------------------------
                                 15                 :  */
                                 16                 : 
                                 17                 : extern "C"
                                 18                 : {
                                 19                 : #include "postgres.h"
                                 20                 : }
                                 21                 : 
                                 22                 : #include <llvm/Support/ErrorHandling.h>
                                 23                 : 
                                 24                 : #include "jit/llvmjit.h"
                                 25                 : 
                                 26                 : #include <new>
                                 27                 : 
                                 28                 : static int fatal_new_handler_depth = 0;
                                 29                 : static std::new_handler old_new_handler = NULL;
                                 30                 : 
                                 31                 : static void fatal_system_new_handler(void);
                                 32                 : #if LLVM_VERSION_MAJOR > 4
                                 33                 : static void fatal_llvm_new_handler(void *user_data, const char *reason, bool gen_crash_diag);
                                 34                 : #if LLVM_VERSION_MAJOR < 14
                                 35                 : static void fatal_llvm_new_handler(void *user_data, const std::string& reason, bool gen_crash_diag);
                                 36                 : #endif
                                 37                 : #endif
                                 38                 : static void fatal_llvm_error_handler(void *user_data, const char *reason, bool gen_crash_diag);
                                 39                 : #if LLVM_VERSION_MAJOR < 14
                                 40                 : static void fatal_llvm_error_handler(void *user_data, const std::string& reason, bool gen_crash_diag);
                                 41                 : #endif
                                 42                 : 
                                 43                 : 
                                 44                 : /*
                                 45                 :  * Enter a section in which C++ and LLVM errors are treated as FATAL errors.
                                 46                 :  *
                                 47                 :  * This is necessary for LLVM as LLVM's error handling for such cases
                                 48                 :  * (exit()ing, throwing std::bad_alloc() if compiled with exceptions, abort())
                                 49                 :  * isn't compatible with postgres error handling.  Thus in sections where LLVM
                                 50                 :  * code, not LLVM generated functions!, is executing, standard new, LLVM OOM
                                 51                 :  * and LLVM fatal errors (some OOM errors masquerade as those) are redirected
                                 52                 :  * to our own error handlers.
                                 53                 :  *
                                 54                 :  * These error handlers use FATAL, because there's no reliable way from within
                                 55                 :  * LLVM to throw an error that's guaranteed not to corrupt LLVM's state.
                                 56                 :  *
                                 57                 :  * To avoid disturbing extensions using C++ and/or LLVM, these handlers are
                                 58                 :  * unset when not executing LLVM code. There is no need to call
                                 59                 :  * llvm_leave_fatal_on_oom() when ERRORing out, error recovery resets the
                                 60                 :  * handlers in that case.
                                 61                 :  */
                                 62                 : void
 1845 andres                     63 CBC        9150 : llvm_enter_fatal_on_oom(void)
                                 64                 : {
                                 65            9150 :     if (fatal_new_handler_depth == 0)
                                 66                 :     {
                                 67            4632 :         old_new_handler = std::set_new_handler(fatal_system_new_handler);
                                 68                 : #if LLVM_VERSION_MAJOR > 4
                                 69            4632 :         llvm::install_bad_alloc_error_handler(fatal_llvm_new_handler);
                                 70                 : #endif
                                 71            4632 :         llvm::install_fatal_error_handler(fatal_llvm_error_handler);
                                 72                 :     }
                                 73            9150 :     fatal_new_handler_depth++;
                                 74            9150 : }
                                 75                 : 
                                 76                 : /*
                                 77                 :  * Leave fatal error section started with llvm_enter_fatal_on_oom().
                                 78                 :  */
                                 79                 : void
                                 80            8311 : llvm_leave_fatal_on_oom(void)
                                 81                 : {
                                 82            8311 :     fatal_new_handler_depth--;
                                 83            8311 :     if (fatal_new_handler_depth == 0)
                                 84                 :     {
                                 85            4177 :         std::set_new_handler(old_new_handler);
                                 86                 : #if LLVM_VERSION_MAJOR > 4
                                 87            4177 :         llvm::remove_bad_alloc_error_handler();
                                 88                 : #endif
                                 89            4177 :         llvm::remove_fatal_error_handler();
                                 90                 :     }
                                 91            8311 : }
                                 92                 : 
                                 93                 : /*
                                 94                 :  * Are we currently in a fatal-on-oom section? Useful to skip cleanup in case
                                 95                 :  * of errors.
                                 96                 :  */
                                 97                 : bool
  573                            98             393 : llvm_in_fatal_on_oom(void)
                                 99                 : {
                                100             393 :     return fatal_new_handler_depth > 0;
                                101                 : }
                                102                 : 
                                103                 : /*
                                104                 :  * Reset fatal error handling. This should only be called in error recovery
                                105                 :  * loops like PostgresMain()'s.
                                106                 :  */
                                107                 : void
 1845                           108            1453 : llvm_reset_after_error(void)
                                109                 : {
                                110            1453 :     if (fatal_new_handler_depth != 0)
                                111                 :     {
                                112             112 :         std::set_new_handler(old_new_handler);
                                113                 : #if LLVM_VERSION_MAJOR > 4
                                114             112 :         llvm::remove_bad_alloc_error_handler();
                                115                 : #endif
                                116             112 :         llvm::remove_fatal_error_handler();
                                117                 :     }
                                118            1453 :     fatal_new_handler_depth = 0;
                                119            1453 : }
                                120                 : 
                                121                 : void
                                122           12284 : llvm_assert_in_fatal_section(void)
                                123                 : {
                                124           12284 :     Assert(fatal_new_handler_depth > 0);
                                125           12284 : }
                                126                 : 
                                127                 : static void
 1845 andres                    128 UBC           0 : fatal_system_new_handler(void)
                                129                 : {
                                130               0 :     ereport(FATAL,
                                131                 :             (errcode(ERRCODE_OUT_OF_MEMORY),
                                132                 :              errmsg("out of memory"),
                                133                 :              errdetail("while in LLVM")));
                                134                 : }
                                135                 : 
                                136                 : #if LLVM_VERSION_MAJOR > 4
                                137                 : static void
                                138               0 : fatal_llvm_new_handler(void *user_data,
                                139                 :                        const char *reason,
                                140                 :                        bool gen_crash_diag)
                                141                 : {
                                142               0 :     ereport(FATAL,
                                143                 :             (errcode(ERRCODE_OUT_OF_MEMORY),
                                144                 :              errmsg("out of memory"),
                                145                 :              errdetail("While in LLVM: %s", reason)));
                                146                 : }
                                147                 : #if LLVM_VERSION_MAJOR < 14
                                148                 : static void
                                149                 : fatal_llvm_new_handler(void *user_data,
                                150                 :                        const std::string& reason,
                                151                 :                        bool gen_crash_diag)
                                152                 : {
                                153                 :     fatal_llvm_new_handler(user_data, reason.c_str(), gen_crash_diag);
                                154                 : }
                                155                 : #endif
                                156                 : #endif
                                157                 : 
                                158                 : static void
                                159               0 : fatal_llvm_error_handler(void *user_data,
                                160                 :                          const char *reason,
                                161                 :                          bool gen_crash_diag)
                                162                 : {
                                163               0 :     ereport(FATAL,
                                164                 :             (errcode(ERRCODE_OUT_OF_MEMORY),
                                165                 :              errmsg("fatal llvm error: %s", reason)));
                                166                 : }
                                167                 : 
                                168                 : #if LLVM_VERSION_MAJOR < 14
                                169                 : static void
                                170                 : fatal_llvm_error_handler(void *user_data,
                                171                 :                          const std::string& reason,
                                172                 :                          bool gen_crash_diag)
                                173                 : {
                                174                 :     fatal_llvm_error_handler(user_data, reason.c_str(), gen_crash_diag);
                                175                 : }
                                176                 : #endif
        

Generated by: LCOV version v1.16-55-g56c0a2a