|
From: <cn...@us...> - 2008-12-30 22:10:33
|
Revision: 113
http://hgengine.svn.sourceforge.net/hgengine/?rev=113&view=rev
Author: cnlohr
Date: 2008-12-30 22:10:30 +0000 (Tue, 30 Dec 2008)
Log Message:
-----------
crash handler
Modified Paths:
--------------
Mercury2/adv_set.c
Mercury2/src/Mercury2.cpp
Added Paths:
-----------
Mercury2/src/MercuryBacktrace.c
Mercury2/src/MercuryBacktrace.h
Mercury2/src/MercuryCrash.c
Mercury2/src/MercuryCrash.h
Modified: Mercury2/adv_set.c
===================================================================
--- Mercury2/adv_set.c 2008-12-30 21:37:42 UTC (rev 112)
+++ Mercury2/adv_set.c 2008-12-30 22:10:30 UTC (rev 113)
@@ -3,17 +3,12 @@
FOLDERS="src"
-SOURCES="src/Mercury2.cpp src/MercuryAsset.cpp \
- src/MercuryNode.cpp src/MercuryPoint.cpp \
- src/MercuryThreads.cpp src/MercuryMath.cpp \
- src/MercuryWindow.cpp src/RenderableNode.cpp \
- src/TransformNode.cpp src/MercuryMatrix.cpp \
- src/Viewport.cpp src/Quad.cpp src/MercuryUtil.cpp \
- src/Texture.cpp src/RawImageData.cpp src/BMPLoader.cpp \
- src/PNGLoader.cpp src/ImageLoader.cpp \
- src/MercuryVBO.cpp src/MSemaphore.cpp \
- src/UpdateThreader.cpp src/HGMDLMesh.cpp \
- src/HGMDLModel.cpp src/MercuryString.cpp"
+SOURCES="src/Mercury2.cpp src/MercuryAsset.cpp src/MercuryNode.cpp src/MercuryPoint.cpp \
+ src/MercuryThreads.cpp src/MercuryMath.cpp src/MercuryWindow.cpp src/RenderableNode.cpp \
+ src/TransformNode.cpp src/MercuryMatrix.cpp src/Viewport.cpp src/Quad.cpp src/MercuryUtil.cpp \
+ src/Texture.cpp src/RawImageData.cpp src/BMPLoader.cpp src/PNGLoader.cpp src/ImageLoader.cpp \
+ src/MercuryVBO.cpp src/MSemaphore.cpp src/UpdateThreader.cpp src/HGMDLMesh.cpp \
+ src/HGMDLModel.cpp src/MercuryString.cpp src/MercuryCrash.c src/MercuryBacktrace.c"
#ifdef USE_LIBXML
SOURCES="$SOURCES src/XMLParser.cpp"
@@ -24,8 +19,8 @@
#endif
PROJ="mercury"
-CFLAGS="$CFLAGS -DHAVE_CONFIG -DHGENGINE -fno-exceptions -fPIC -Isrc"
-LDFLAGS="$LDFLAGS -rdynamic -g -fPIC"
+CFLAGS="$CFLAGS -DHAVE_CONFIG -DHGENGINE -fno-exceptions -fPIC -Isrc -g "
+LDFLAGS="$LDFLAGS -rdynamic -g -fPIC "
/*
* (c) 2007-2008 Charles Lohr
Modified: Mercury2/src/Mercury2.cpp
===================================================================
--- Mercury2/src/Mercury2.cpp 2008-12-30 21:37:42 UTC (rev 112)
+++ Mercury2/src/Mercury2.cpp 2008-12-30 22:10:30 UTC (rev 113)
@@ -8,6 +8,9 @@
#include <RenderableNode.h>
+#include <MercuryCrash.h>
+#include <MercuryBacktrace.h>
+
MSemaphore UpdateLoopGo;
void* UpdateThread(void* node)
{
@@ -19,11 +22,23 @@
return NULL;
}
+int SignalHandler( int signal )
+{
+ char buffer[2048];
+ printf( "Fatal error encountered in Mercury 2: %s\n", cn_get_crash_description( signal ) );
+ cnget_backtrace( 1, buffer, 2047 );
+ printf( "%s\n", buffer );
+
+ return 0; //Continue regular crash.
+}
+
int main()
{
unsigned long m_count = 0;
long m_time;
-
+
+ cnset_execute_on_crash( SignalHandler );
+
MercuryWindow* w = MercuryWindow::MakeWindow();
MercuryNode* root = new MercuryNode();
Added: Mercury2/src/MercuryBacktrace.c
===================================================================
--- Mercury2/src/MercuryBacktrace.c (rev 0)
+++ Mercury2/src/MercuryBacktrace.c 2008-12-30 22:10:30 UTC (rev 113)
@@ -0,0 +1,611 @@
+#include "MercuryBacktrace.h"
+
+
+#ifdef WIN32
+#define _CWINDOWS
+#else
+#if defined( MACOSX ) || defined( __APPLE__ )
+#define _CMAC
+#else
+#define _CLINUX
+#endif
+#endif
+
+
+
+#if defined ( _CWINDOWS )
+#define CPU_X86
+#include <windows.h>
+#include <dbghelp.h>
+#pragma comment( lib, "dbghelp.lib" )
+/*Since we have inline code in windows, there are
+ warnings associated with disabling optimization,
+ ignore them. */
+#pragma warning( disable : 4748)
+/*Ignore CRT_SECURE_NO_DEPRECIATE for snprintf */
+#pragma warning( disable : 4996)
+#elif defined( _CMAC ) || defined( _CLINUX )
+
+#ifdef _CLINUX
+#include <malloc.h>
+#include <execinfo.h>
+#define HAVE_EXECINFO
+#endif
+
+
+#ifdef HAVE_LIBIBERTY
+
+/*Ok, even StepMania had this question!:
+ This is in libiberty. Where is it declared? */
+#ifdef __cplusplus
+extern "C" {
+#endif
+char *cplus_demangle (const char *mangled, int options);
+#ifdef __cplusplus
+};
+#endif
+#endif
+
+#if !defined( __USE_GNU ) && !defined( _CMAC )
+
+typedef struct
+{
+ __const char *dli_fname; /* File name of defining object. */
+ void *dli_fbase; /* Load address of that object. */
+ __const char *dli_sname; /* Name of nearest symbol. */
+ void *dli_saddr; /* Exact value of nearest symbol. */
+} Dl_info;
+
+extern int dladdr (__const void *__address, Dl_info *__info);
+extern void *dlopen (__const char *__file, int __mode);
+extern int dlclose (void *__handle);
+extern void *dlsym (void *__restrict __handle,
+ __const char *__restrict __name);
+
+#endif
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+int bUseAddr2Line, DBGSetup = 0;
+
+#endif
+
+
+
+
+struct BacktraceContext
+{
+ int dummy;
+#if defined( _CWINDOWS)
+ CONTEXT context;
+ HANDLE hThread;
+ HANDLE hProcess;
+#endif
+};
+
+#include <stdio.h>
+
+int GetBacktrace( void **buf, unsigned size, struct BacktraceContext *ctx );
+int GetBTName( const void * ptr, char * str, int maxlen, struct BacktraceContext * ctx );
+void SetupDBGHelp();
+
+
+int cnget_backtrace( int SkipFirst, char * buffer, int max_size )
+{
+ char * tmpbuf = buffer;
+
+ void * buf[256];
+ int i = 0;
+ SetupDBGHelp();
+ GetBacktrace( (void **)buf, 256, 0 );
+
+ for( ; i < SkipFirst; i++ )
+ if( buf[i] == 0 )
+ return 0;
+
+ while( buf[i] != 0 )
+ {
+ int space_left = max_size-(int)(tmpbuf-buffer)-2;
+ tmpbuf+=GetBTName( buf[i], tmpbuf, space_left, 0 );
+ *tmpbuf='\n';
+ tmpbuf++;
+ *tmpbuf='\0';
+ i++;
+ }
+
+ return i-1;
+}
+
+
+
+
+
+
+
+#if defined( _CMAC ) || defined( _CLINUX )
+//Based off of http://stackoverflow.com/questions/289820/getting-the-current-stack-trace-on-mac-os-x
+
+int GetBacktrace( void **buffer, unsigned size, struct BacktraceContext *ctx )
+{
+#ifdef HAVE_EXECINFO
+ return backtrace( buffer, size );
+#else
+ //Todo: See if the return is beyond the end of a function.
+
+ void **frame = (void **)__builtin_frame_address(0);
+ void **bp = ( void **)(*frame);
+ void *ip = frame[1];
+ int i;
+
+ for ( i = 0; bp && ip && i < size; i++ )
+ {
+ *(buffer++) = ip;
+ ip = bp[1];
+ bp = (void**)(bp[0]);
+ }
+
+ return i;
+#endif
+}
+
+int Demangle( char * out, int maxlen, const char * in )
+{
+ *out = 0;
+ if( !in )
+ return 0;
+#ifdef HAVE_LIBIBERTY
+ int pos = 0;
+ char * demangled = cplus_demangle( in, 0 );
+ if( !demangled )
+ return 0;
+ while( demangled[pos] != 0 && pos + 1 < maxlen )
+ {
+ out[pos] = demangled[pos];
+ pos++;
+ }
+ out[pos] = 0;
+ free( demangled );
+ return pos;
+#else
+ return 0;
+#endif
+}
+
+
+int Addr2Line( char * out, char * demangled, int maxlen, const char * file, const void * offset )
+{
+ int tmp;
+ char execline[1024];
+ char buffer[1024];
+ int fds[2];
+ int readbytes;
+ int newlinepos;
+ int slashpos;
+
+ *out = 0;
+ *demangled = 0;
+
+ if( strlen( file ) < 1 )
+ return 0;
+
+ tmp = open( file, O_RDONLY );
+ if( !tmp )
+ return 0;
+ close( tmp );
+
+ if( pipe( fds ) != 0 )
+ return 0;
+
+#ifdef _CMAC
+ sprintf( execline, "atos -o %s 0x%lx 1>&%d", file, (unsigned long)offset, fds[1] );
+ printf( "Crash Progress: Executing command: %s\n", execline );
+#else
+ sprintf( execline, "addr2line -fC -e %s 0x%lx 1>&%d", file, (unsigned long)offset, fds[1] );
+#endif
+ system( execline );
+
+ readbytes = read( fds[0], buffer, 1024 );
+ if( readbytes + 1 >= maxlen )
+ readbytes = maxlen - 1;
+ close( fds[0] );
+ close( fds[1] );
+
+ //Something went wrong.
+ if( readbytes < 3 )
+ return 0;
+#ifdef _CMAC
+ memcpy( out, buffer, readbytes - 1 );
+ out[readbytes] = 0;
+ return 1;
+#else
+ //??:0 is a bad return value.
+ if( buffer[0] == '?' )
+ return 0;
+
+ if( strstr( buffer, ": No such file" ) > 0 )
+ return 0;
+
+ newlinepos = 0;
+ for( tmp = 0; tmp < readbytes; tmp++ )
+ if( buffer[tmp] == '\n' ) break;
+ newlinepos = tmp;
+
+ if( tmp == readbytes )
+ return 0;
+
+ memcpy( demangled, buffer, newlinepos );
+ demangled[newlinepos] = 0;
+
+ slashpos = 0;
+ for( tmp = newlinepos; tmp < readbytes; tmp++ )
+ {
+ if( buffer[tmp] == '/' ) slashpos = tmp;
+ }
+
+ if( slashpos == 0 )
+ slashpos = newlinepos;
+ slashpos++;
+ if( slashpos >= readbytes )
+ slashpos = 0;
+
+ readbytes -= slashpos;
+ memcpy( out, buffer + slashpos, readbytes );
+
+ if( readbytes > 1 )
+ out[readbytes-1] = 0;
+ else
+ out[readbytes] = 0;
+
+ return readbytes;
+#endif
+
+}
+
+
+int GetBTName( const void * ptr, char * str, int maxlen, struct BacktraceContext * ctx )
+{
+ char demangled[1024], floc[1024];
+ const char * symbol;
+ Dl_info dli;
+ int c = 0;
+ int useaddr=0;
+
+ c = snprintf(str, maxlen, " [%0*lx]", (int)sizeof(void*)*2, (long unsigned int)ptr );
+
+ if (dladdr(ptr, &dli))
+ {
+ unsigned offset;
+ symbol = dli.dli_sname;
+
+ if( dli.dli_fbase && dli.dli_fname )
+ {
+ if( bUseAddr2Line )
+ {
+ unsigned long actualptr = (unsigned long)ptr;
+ int fnamelen = strlen( dli.dli_fname );
+
+ //If it's a .so, we need ot check relatively to the start of the .so
+ //since it was compiled with -fPIC
+
+ if( dli.dli_fname[fnamelen-3] == '.' &&
+ dli.dli_fname[fnamelen-2] == 's' &&
+ dli.dli_fname[fnamelen-1] == 'o' )
+ {
+ actualptr-=(unsigned long)dli.dli_fbase;
+ }
+
+ if( Addr2Line( floc, demangled, 1024, dli.dli_fname, (void*)actualptr ) )
+ {
+ symbol = demangled;
+ useaddr=1;
+ }
+ }
+ }
+
+ //If addr2line doesn't work right, we can try using demangle from libiberty
+ if( !useaddr )
+ if( Demangle( demangled, 1024, symbol ) )
+ symbol = demangled;
+
+ if( symbol )
+ {
+ offset = ptr - dli.dli_saddr;
+ c += snprintf(str+c, maxlen-c, " (%s+0x%x (0x%lx))", symbol, offset,(unsigned long)dli.dli_saddr );
+ }
+ if( dli.dli_fbase && dli.dli_fname )
+ {
+ if( useaddr )
+ c += snprintf(str+c, maxlen-c, " [%s]", floc );
+ else
+ c += snprintf(str+c, maxlen-c, " [%s+0x%lx]", dli.dli_fname, (unsigned long)dli.dli_fbase );
+ }
+ }
+ return c;
+}
+
+void SetupDBGHelp()
+{
+ int fds[2];
+ char execline[1024];
+ if( DBGSetup )
+ return;
+ DBGSetup = 1;
+ pipe( fds );
+
+#ifdef _CMAC
+ sprintf( execline, "atos 2>&%d", fds[0] );
+#else
+ sprintf( execline, "addr2line -v 1>&%d", fds[0] );
+#endif
+
+ if( system( execline ) == 0 )
+ bUseAddr2Line = 1;
+ else
+ bUseAddr2Line = 0;
+ close( fds[0] );
+ close( fds[1] );
+}
+
+
+#elif defined( _CWINDOWS )
+
+int wGetCurrentContext( struct BacktraceContext *CTX )
+{
+ CTX->context.ContextFlags = CONTEXT_CONTROL;
+ CTX->hThread = GetCurrentThread();
+ CTX->hProcess = GetCurrentProcess();
+#ifdef CPU_X86
+ //no way to do it except in ASM, see below.
+#else
+ if( !RtlCaptureContext( &CTX->context ) )
+ {
+ printf( "Could not launch context helper.\n" );
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int GetBacktrace( void **buf, size_t size, struct BacktraceContext *CTX )
+{
+ const void **pLast = buf + size - 1;
+ int bFirst = 1;
+ DWORD MachineType;
+ CONTEXT * pContext;
+ HANDLE hThread;
+ HANDLE hProcess;
+ struct BacktraceContext MCTX; //in case we don't have a context.
+ int ActuallyThisThread = 0;
+ if( CTX == 0 )
+ {
+ if( wGetCurrentContext( &MCTX ) != 0)
+ return -2;
+ pContext = &(MCTX.context);
+ hThread = MCTX.hThread;
+ hProcess = MCTX.hProcess;
+ ActuallyThisThread = 1;
+ }
+ else
+ {
+ pContext = &(CTX->context);
+ hThread = CTX->hThread;
+ hProcess = CTX->hProcess;
+ }
+
+ {
+ size_t count = 0;
+ STACKFRAME64 sf64;
+
+#ifdef CPU_X86
+ CONTEXT Context;
+ MachineType = IMAGE_FILE_MACHINE_I386;
+
+ if( ActuallyThisThread )
+ {
+ ZeroMemory( &Context, sizeof( CONTEXT ) );
+
+ //http://jpassing.wordpress.com/2008/03/12/walking-the-stack-of-the-current-thread/
+ __asm
+ {
+ Label:
+ mov [Context.Ebp], ebp;
+ mov [Context.Esp], esp;
+ mov eax, [Label];
+ mov [Context.Eip], eax;
+ }
+ Context.ContextFlags = CONTEXT_CONTROL;
+ pContext = &Context;
+ }
+
+ memset( &sf64, '\0', sizeof sf64 );
+ sf64.AddrPC.Offset = Context.Eip;
+ sf64.AddrPC.Mode = AddrModeFlat;
+ sf64.AddrFrame.Offset = Context.Ebp;
+ sf64.AddrFrame.Mode = AddrModeFlat;
+ sf64.AddrStack.Offset = Context.Esp;
+ sf64.AddrStack.Segment = AddrModeFlat;
+#else
+ MachineType = IMAGE_FILE_MACHINE_AMD64;
+ memset( &sf64, '\0', sizeof sf64 );
+ sf64.AddrPC.Offset = Context.Rip;
+ sf64.AddrPC.Mode = AddrModeFlat;
+ sf64.AddrFrame.Offset = Context.Rsp;
+ sf64.AddrFrame.Mode = AddrModeFlat;
+ sf64.AddrStack.Offset = Context.Rsp;
+ sf64.AddrStack.Segment = AddrModeFlat;
+#endif
+ while( 1 )
+ {
+ int ret;
+ SetLastError( 0 );
+ ret = StackWalk64( MachineType, hProcess, hThread, &sf64, pContext, 0,
+ SymFunctionTableAccess64, SymGetModuleBase64, 0 );
+
+ if( !ret )
+ {
+ break;
+ }
+
+ if( sf64.AddrPC.Offset != 0)
+ *buf = (void*)sf64.AddrPC.Offset;
+ else
+ *buf = (void*)-1;
+ buf++;
+ count++;
+ if( count + 1 >= size ) break;
+ }
+ }
+ SetLastError( 0 );
+ *buf = 0;
+
+ return 0;
+}
+
+int GetBTName( const void * ptr, char * str, int maxlen, struct BacktraceContext * ctx )
+{
+ char lsymbol[1024], lfile[1024];
+ IMAGEHLP_LINE64 Line;
+ PSYMBOL_INFO Symbol;
+ HANDLE hProcess;
+ int i, pwd = 0;
+
+ Symbol = malloc( sizeof( SYMBOL_INFO ) + 501 );
+ Line.SizeOfStruct = sizeof( IMAGEHLP_LINE64 );
+
+ Symbol->MaxNameLen = 500;
+
+ if( ctx )
+ hProcess = ctx->hProcess;
+ else
+ hProcess = GetCurrentProcess();
+
+ i = SymFromAddr( hProcess, (DWORD64)ptr, 0, Symbol );
+ if( !i )
+ {
+ return _snprintf( str, maxlen, "%p (unknown)", ptr );
+ }
+ i = SymGetLineFromAddr64( hProcess, (DWORD64)ptr, &pwd, &Line );
+
+ if( i == 0)
+ {
+ Line.FileName = 0;
+ Line.LineNumber = 0;
+ }
+
+ for( i = 0; i < 1023; i++ )
+ {
+ TCHAR c = Symbol->Name[i];
+ lsymbol[i] = (char)c;
+ if( c < 28 ) break;
+ }
+ lsymbol[i] = 0;
+
+ if( Line.FileName )
+ {
+ for( i = 0; i < 1023; i++ )
+ {
+ TCHAR c = Line.FileName[i];
+ lfile[i] = (char)c;
+ if( c < 28 ) break;
+ }
+ lfile[i] = 0;
+ }
+
+ if( Line.FileName )
+ return _snprintf( str, maxlen, "%p %s (%s:%d)", ptr, lsymbol, lfile, Line.LineNumber );
+ else
+ return _snprintf( str, maxlen, "%p %s", ptr, lsymbol );
+}
+
+//Base off of example from http://www.debuginfo.com/example
+
+void SetupDBGHelp()
+{
+ int bRet = 0;
+ static int already_set_up = 0;
+ DWORD Options;
+
+ if (already_set_up) return;
+ already_set_up = 1;
+
+ Options = SymGetOptions();
+ Options |= SYMOPT_DEBUG;
+ Options |= SYMOPT_LOAD_LINES;
+ SymSetOptions( Options );
+
+ bRet = SymInitialize (
+ GetCurrentProcess(), // Process handle of the current process
+ NULL, // No user-defined search path -> use default
+ TRUE // Load symbols for all modules in the current process
+ );
+
+ if( !bRet )
+ {
+ printf("Error: SymInitialize() failed. Error code: %u \n", GetLastError());
+ return;
+ }
+
+ {
+ TCHAR pFileName[2048];
+
+ DWORD64 ModBase;
+ DWORD64 BaseAddr = 0x10000000;
+ DWORD FileSize = 0;
+
+ GetModuleFileName( 0, pFileName, 2048 );
+
+ if( !GetFileSize( pFileName, &FileSize ) )
+ return;
+
+ ModBase = SymLoadModule64 (
+ GetCurrentProcess(),
+ NULL,
+ (PSTR)pFileName,
+ NULL,
+ BaseAddr,
+ FileSize
+ );
+
+ if( ModBase == 0 )
+ {
+ printf( "Error: SymLoadModule64() failed. Error code: %u \n" , GetLastError());
+ return;
+ }
+ }
+
+
+ return;
+}
+
+#else
+#error Neither _CWINDOWS, _CMAC OR _CLINUX are defined!
+#endif
+
+
+/*
+ * (c) 2003-2008 Glenn Maynard, Steve Checkoway, Avery Lee, Charles Lohr
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons to
+ * whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
Added: Mercury2/src/MercuryBacktrace.h
===================================================================
--- Mercury2/src/MercuryBacktrace.h (rev 0)
+++ Mercury2/src/MercuryBacktrace.h 2008-12-30 22:10:30 UTC (rev 113)
@@ -0,0 +1,39 @@
+#ifndef _HGBACKTRACE_H
+#define _HGBACKTRACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int cnget_backtrace( int SkipFirst, char * buffer, int max_size );
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
+
+/*
+ * (c) 2003-2008 Glenn Maynard, Steve Checkoway, Avery Lee, Charles Lohr
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons to
+ * whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
Added: Mercury2/src/MercuryCrash.c
===================================================================
--- Mercury2/src/MercuryCrash.c (rev 0)
+++ Mercury2/src/MercuryCrash.c 2008-12-30 22:10:30 UTC (rev 113)
@@ -0,0 +1,214 @@
+#include "MercuryCrash.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef WIN32
+#define _CWINDOWS
+#else
+#if defined( MACOSX ) || defined( __APPLE__ )
+#define _CMAC
+#else
+#define _CLINUX
+#endif
+#endif
+
+
+
+#if defined( _CLINUX ) || defined( _CMAC )
+
+#ifdef _CLINUX
+
+#ifndef __USE_POSIX
+#define __USE_POSIX
+#include <signal.h>
+#undef__USE_POSIX
+#else
+#include <signal.h>
+#endif
+
+#include <bits/siginfo.h>
+
+#else
+
+#include <signal.h>
+
+#endif
+
+int inCrashHandler = 0;
+
+static int msignals[] =
+{
+ SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGABRT,
+ SIGQUIT, SIGSEGV, SIGTRAP, SIGTERM, SIGVTALRM, SIGXCPU, SIGXFSZ,
+#if defined(HAVE_DECL_SIGPWR) && HAVE_DECL_SIGPWR
+ SIGPWR,
+#endif
+#if defined(HAVE_DECL_SIGUSR1) && HAVE_DECL_SIGUSR1
+ SIGUSR1,
+#endif
+ -1
+};
+
+static const struct ExceptionLookup {
+ int code;
+ const char *name;
+} exceptions[]={
+ { SIGALRM, "SIGALRM" },
+ { SIGBUS, "SIGBUS" },
+ { SIGFPE, "SIGFPE" },
+ { SIGINT, "SIGINT" },
+ { SIGABRT, "SIGABRT" },
+ { SIGQUIT, "SIGQUIT" },
+ { SIGSEGV, "Segmentation Fault", },
+ { SIGTRAP, "SIGTRAP", },
+ { SIGTERM, "SIGTERM", },
+ { SIGXCPU, "SIGXCPU", },
+ { SIGXFSZ, "SIGXFSZ", },
+ { 0, "Unknown Exception", },
+ { 0 },
+};
+
+FNType chHandler;
+
+static void SigHandler( int signal, siginfo_t *si, void *ucp )
+{
+ if( inCrashHandler )
+ exit( -1 );
+
+ inCrashHandler = 1;
+
+ if( chHandler( signal ) == 0x12121212 )
+ return;
+
+ inCrashHandler = 0;
+ if( signal == SIGINT || signal == SIGQUIT )
+ {
+ printf( "Ctrl+Break Hit, Exit.\n" );
+ exit( 1 );
+ return;
+ }
+
+ if( signal == SIGTERM || signal == SIGHUP )
+ return;
+
+ struct sigaction sa;
+ sa.sa_flags = 0;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_handler = SIG_DFL;
+
+ struct sigaction old;
+ sigaction( signal, &sa, &old );
+ raise( signal );
+ sigaction( signal, &old, NULL );
+}
+
+
+int cnset_execute_on_crash( FNType fn )
+{
+ int i;
+ struct sigaction sa;
+ chHandler = fn;
+
+ sa.sa_flags = 0;
+ sa.sa_flags |= SA_NODEFER;
+ sa.sa_flags |= SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+
+ // Set up our signal handlers.
+ sa.sa_sigaction = SigHandler;
+ for( i = 0; msignals[i] != -1; ++i )
+ sigaction( msignals[i], &sa, NULL );
+
+ // Block SIGPIPE, so we get EPIPE.
+ sa.sa_handler = SIG_IGN;
+ sigaction( SIGPIPE, &sa, NULL );
+ return 0;
+}
+
+#elif defined( _CWINDOWS )
+#include <windows.h>
+
+FNType top;
+
+long __stdcall cnException(
+ struct _EXCEPTION_POINTERS * filter)
+{
+ int ret = 0;
+ ret = top( filter->ExceptionRecord->ExceptionCode );
+ if( ret == 0x12121212 )
+ return EXCEPTION_CONTINUE_EXECUTION;
+ else
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int cnset_execute_on_crash( FNType fn )
+{
+ top = fn;
+ SetUnhandledExceptionFilter(cnException);
+ return 0;
+}
+
+static const struct ExceptionLookup {
+ DWORD code;
+ const char *name;
+} exceptions[]={
+ { EXCEPTION_ACCESS_VIOLATION, "Access Violation" },
+ { EXCEPTION_BREAKPOINT, "Breakpoint" },
+ { EXCEPTION_FLT_DENORMAL_OPERAND, "FP Denormal Operand" },
+ { EXCEPTION_FLT_DIVIDE_BY_ZERO, "FP Divide-by-Zero" },
+ { EXCEPTION_FLT_INEXACT_RESULT, "FP Inexact Result" },
+ { EXCEPTION_FLT_INVALID_OPERATION, "FP Invalid Operation" },
+ { EXCEPTION_FLT_OVERFLOW, "FP Overflow", },
+ { EXCEPTION_FLT_STACK_CHECK, "FP Stack Check", },
+ { EXCEPTION_FLT_UNDERFLOW, "FP Underflow", },
+ { EXCEPTION_INT_DIVIDE_BY_ZERO, "Integer Divide-by-Zero", },
+ { EXCEPTION_INT_OVERFLOW, "Integer Overflow", },
+ { EXCEPTION_PRIV_INSTRUCTION, "Privileged Instruction", },
+ { EXCEPTION_ILLEGAL_INSTRUCTION, "Illegal instruction" },
+ { EXCEPTION_INVALID_HANDLE, "Invalid handle" },
+ { EXCEPTION_STACK_OVERFLOW, "Stack overflow" },
+ { 0xe06d7363, "Unhandled Microsoft C++ Exception", },
+ { 0, "UNKNOWN EXCEPTION", },
+ { 0 },
+};
+
+
+#endif
+
+
+const char * cn_get_crash_description( int code )
+{
+ int i;
+
+ for( i = 0; exceptions[i].code; ++i )
+ if( exceptions[i].code == code )
+ return exceptions[i].name;
+
+ return exceptions[i].name;
+}
+
+
+/*
+ * (c) 2003-2008 Glenn Maynard, Steve Checkoway, Avery Lee, Charles Lohr
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons to
+ * whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
Added: Mercury2/src/MercuryCrash.h
===================================================================
--- Mercury2/src/MercuryCrash.h (rev 0)
+++ Mercury2/src/MercuryCrash.h 2008-12-30 22:10:30 UTC (rev 113)
@@ -0,0 +1,44 @@
+#ifndef _HGCRASH_H
+#define _HGCRASH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//If you return 0x12121212, it will attempt not to crash. Otherwise, it will just do whatever it feels it should.
+typedef int (*FNType)( int signal );
+
+int cnset_execute_on_crash( FNType fn );
+const char * cn_get_crash_description( int code );
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
+
+
+/*
+ * (c) 2003-2008 Glenn Maynard, Steve Checkoway, Avery Lee, Charles Lohr
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons to
+ * whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|