1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
/*!
\file error.c
\brief Various error-handling functions
This file contains functions dealing with error reporting and termination
\author George
\date 1/1/2007
\version\verbatim $Id: error.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
*/
#define _GK_ERROR_C_ /* this is needed to properly declare the gk_jub* variables
as an extern function in GKlib.h */
#include <GKlib.h>
/* These are the jmp_buf for the graceful exit in case of severe errors.
Multiple buffers are defined to allow for recursive invokation. */
#define MAX_JBUFS 128
__thread int gk_cur_jbufs=-1;
__thread jmp_buf gk_jbufs[MAX_JBUFS];
__thread jmp_buf gk_jbuf;
typedef void (*gksighandler_t)(int);
/* These are the holders of the old singal handlers for the trapped signals */
static __thread gksighandler_t old_SIGMEM_handler; /* Custom signal */
static __thread gksighandler_t old_SIGERR_handler; /* Custom signal */
static __thread gksighandler_t old_SIGMEM_handlers[MAX_JBUFS]; /* Custom signal */
static __thread gksighandler_t old_SIGERR_handlers[MAX_JBUFS]; /* Custom signal */
/* The following is used to control if the gk_errexit() will actually abort or not.
There is always a single copy of this variable */
static int gk_exit_on_error = 1;
/*************************************************************************/
/*! This function sets the gk_exit_on_error variable
*/
/*************************************************************************/
void gk_set_exit_on_error(int value)
{
gk_exit_on_error = value;
}
/*************************************************************************/
/*! This function prints an error message and exits
*/
/*************************************************************************/
void errexit(char *f_str,...)
{
va_list argp;
va_start(argp, f_str);
vfprintf(stderr, f_str, argp);
va_end(argp);
if (strlen(f_str) == 0 || f_str[strlen(f_str)-1] != '\n')
fprintf(stderr,"\n");
fflush(stderr);
if (gk_exit_on_error)
exit(-2);
/* abort(); */
}
/*************************************************************************/
/*! This function prints an error message and raises a signum signal
*/
/*************************************************************************/
void gk_errexit(int signum, char *f_str,...)
{
va_list argp;
va_start(argp, f_str);
vfprintf(stderr, f_str, argp);
va_end(argp);
fprintf(stderr,"\n");
fflush(stderr);
if (gk_exit_on_error)
raise(signum);
}
/***************************************************************************/
/*! This function sets a number of signal handlers and sets the return point
of a longjmp
*/
/***************************************************************************/
int gk_sigtrap()
{
if (gk_cur_jbufs+1 >= MAX_JBUFS)
return 0;
gk_cur_jbufs++;
old_SIGMEM_handlers[gk_cur_jbufs] = signal(SIGMEM, gk_sigthrow);
old_SIGERR_handlers[gk_cur_jbufs] = signal(SIGERR, gk_sigthrow);
return 1;
}
/***************************************************************************/
/*! This function sets the handlers for the signals to their default handlers
*/
/***************************************************************************/
int gk_siguntrap()
{
if (gk_cur_jbufs == -1)
return 0;
signal(SIGMEM, old_SIGMEM_handlers[gk_cur_jbufs]);
signal(SIGERR, old_SIGERR_handlers[gk_cur_jbufs]);
gk_cur_jbufs--;
return 1;
}
/*************************************************************************/
/*! This function is the custome signal handler, which all it does is to
perform a longjump to the most recent saved environment
*/
/*************************************************************************/
void gk_sigthrow(int signum)
{
longjmp(gk_jbufs[gk_cur_jbufs], signum);
}
/***************************************************************************
* This function sets a number of signal handlers and sets the return point
* of a longjmp
****************************************************************************/
void gk_SetSignalHandlers()
{
old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler);
old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler);
}
/***************************************************************************
* This function sets the handlers for the signals to their default handlers
****************************************************************************/
void gk_UnsetSignalHandlers()
{
signal(SIGMEM, old_SIGMEM_handler);
signal(SIGERR, old_SIGERR_handler);
}
/*************************************************************************
* This function is the handler for SIGUSR1 that implements the cleaning up
* process prior to a non-local exit.
**************************************************************************/
void gk_NonLocalExit_Handler(int signum)
{
longjmp(gk_jbuf, signum);
}
/*************************************************************************/
/*! \brief Thread-safe implementation of strerror() */
/**************************************************************************/
char *gk_strerror(int errnum)
{
#if defined(WIN32) || defined(__MINGW32__)
return strerror(errnum);
#else
#ifndef SUNOS
static __thread char buf[1024];
strerror_r(errnum, buf, 1024);
buf[1023] = '\0';
return buf;
#else
return strerror(errnum);
#endif
#endif
}
/*************************************************************************
* This function prints a backtrace of calling functions
**************************************************************************/
void PrintBackTrace()
{
#ifdef HAVE_EXECINFO_H
void *array[10];
int i, size;
char **strings;
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
printf("Obtained %d stack frames.\n", size);
for (i=0; i<size; i++) {
printf("%s\n", strings[i]);
}
free(strings);
#endif
}
|