diff --git a/lib/include/ert/util/util.h b/lib/include/ert/util/util.h index fff69fc5ac..073fe8581d 100644 --- a/lib/include/ert/util/util.h +++ b/lib/include/ert/util/util.h @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -387,6 +388,13 @@ typedef bool (walk_dir_callback_ftype) (const char * , /* The current director CONTAINS_HEADER(size_t); #undef CONTAINS_HEADER +/* Redefining sighandler_t in case it isn't defined (Windows). +This is harmless on other platforms. */ +typedef void (*sighandler_t)(int); +/* When installing our abort handler, remeber if there was a previous one, +* so we can call that afterwards */ +extern sighandler_t previous_abort_handler; + #ifdef _MSC_VER #define util_abort(fmt , ...) util_abort__(__FILE__ , __func__ , __LINE__ , fmt , __VA_ARGS__) #elif __GNUC__ diff --git a/lib/util/util.c b/lib/util/util.c index 84048565e2..c23445a835 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -4405,12 +4405,17 @@ char * util_realloc_sprintf(char * s , const char * fmt , ...) { The various signals can be found in: /usr/include/bits/signum.h */ +sighandler_t previous_abort_handler = SIG_IGN; -void util_abort_signal(int signal) { - util_abort("Program received signal:%d\n" , signal); +void util_abort_signal(int the_signal) { + if (previous_abort_handler == SIG_IGN) { + signal(SIGABRT, SIG_DFL); + } else { + signal(SIGABRT, previous_abort_handler); + } + util_abort("Program received signal:%d\n" , the_signal); } - void util_install_signals(void) { #ifdef HAVE_SIGBUS signal(SIGBUS , util_abort_signal); @@ -4419,7 +4424,14 @@ void util_install_signals(void) { signal(SIGSEGV , util_abort_signal); /* Segmentation violation, i.e. overwriting memory ... */ signal(SIGTERM , util_abort_signal); /* If killing the enkf program with SIGTERM (the default kill signal) you will get a backtrace. Killing with SIGKILL (-9) will not give a backtrace.*/ - signal(SIGABRT , util_abort_signal); /* Signal abort. */ + + + sighandler_t previous_abort = signal(SIGABRT , util_abort_signal); /* Signal abort. */ + if (previous_abort != util_abort_signal) { + /* Let previously installed abort handler (i.e. python faulthandler) be called in the end */ + previous_abort_handler = previous_abort; + } + signal(SIGILL , util_abort_signal); /* Signal illegal instruction. */ signal(SIGFPE , util_abort_signal); /* Floating point exception */ } @@ -4429,10 +4441,7 @@ void util_install_signals(void) { have not been modified from the default state. */ -static void update_signal( int signal_nr ) { - /* Redefining sighandler_t in case it isn't defined (Windows). - This is harmless on other platforms. */ - typedef void (*sighandler_t)(int); +static void update_signal( int signal_nr) { sighandler_t current_handler = signal(signal_nr , SIG_DFL); if (current_handler == SIG_DFL) diff --git a/lib/util/util_abort_gnu.c b/lib/util/util_abort_gnu.c index e3daca3883..a2a4488a54 100644 --- a/lib/util/util_abort_gnu.c +++ b/lib/util/util_abort_gnu.c @@ -248,8 +248,10 @@ static char* __abort_program_message; void util_abort__(const char * file , const char * function , int line , const char * fmt , ...) { util_abort_test_intercept( function ); - pthread_mutex_lock( &__abort_mutex ); /* Abort before unlock() */ - { + /* if we cannot lock, presumably we could not open a file and we are calling + * util_abort recursively */ + int lock_status = pthread_mutex_trylock( &__abort_mutex ); + if (lock_status == 0) { char * filename = NULL; FILE * abort_dump = NULL; @@ -277,7 +279,7 @@ void util_abort__(const char * file , const char * function , int line , const c addr2line; the call is based on util_spawn() which is currently only available on POSIX. */ - const bool include_backtrace = true; + const bool include_backtrace = (lock_status == 0); if (include_backtrace) { if (__abort_program_message != NULL) { #if !defined(__GLIBC__) @@ -313,10 +315,17 @@ void util_abort__(const char * file , const char * function , int line , const c } chmod(filename, 00644); // -rw-r--r-- free(filename); + pthread_mutex_unlock(&__abort_mutex); + } else { + /* Failure in util_abort. Print basic error message and exit. */ + fprintf(stderr, "Error while handling error. Exiting. File: %s Function: %s, Line: %d\n", file, function, line); + fprintf(stderr , "Error message: "); + va_list ap; + va_start(ap , fmt); + vfprintf(stderr , fmt , ap); + va_end(ap); } - pthread_mutex_unlock(&__abort_mutex); - signal(SIGABRT, SIG_DFL); abort(); } diff --git a/lib/util/util_abort_simple.c b/lib/util/util_abort_simple.c index 7345a356db..2c08da0506 100644 --- a/lib/util/util_abort_simple.c +++ b/lib/util/util_abort_simple.c @@ -29,7 +29,6 @@ void util_abort__(const char * file , const char * function , int line , const c } fprintf(stderr,"-----------------------------------------------------------------\n"); - signal(SIGABRT , SIG_DFL); fprintf(stderr , "Aborting ... \n"); assert(0); abort(); diff --git a/python/ecl/__init__.py b/python/ecl/__init__.py index 20fe130f43..3e876fe6ad 100644 --- a/python/ecl/__init__.py +++ b/python/ecl/__init__.py @@ -53,7 +53,6 @@ alternative fails, the loader will try the default load behaviour before giving up completely. """ -import os import os.path import sys @@ -135,8 +134,8 @@ def __init__(self, prototype, bind=True): from .util.util import EclVersion from .util.util import updateAbortSignals -if not os.getenv('ECL_SKIP_SIGNAL'): - updateAbortSignals( ) + +updateAbortSignals( ) def root(): """ diff --git a/python/ecl/util/util/install_abort_signals.py b/python/ecl/util/util/install_abort_signals.py index 70b9a22be0..2af10ec0dd 100644 --- a/python/ecl/util/util/install_abort_signals.py +++ b/python/ecl/util/util/install_abort_signals.py @@ -1,15 +1,17 @@ from ecl import EclPrototype - +import os def installAbortSignals(): - install_signals() + if not os.getenv('ECL_SKIP_SIGNAL'): + install_signals() def updateAbortSignals(): """ Will install the util_abort_signal for all UNMODIFIED signals. """ - update_signals() + if not os.getenv('ECL_SKIP_SIGNAL'): + update_signals() install_signals = EclPrototype("void util_install_signals()")