Split out itoa, SignalName, and SignalCodeName. All of these are macros, so testing for them directly is okay (at least on OS X and linux). If some other system doesn't implement them as macros, then checks for them can be added to the configure.ac script.

All of these can be called under crash conditions.
This commit is contained in:
Steve Checkoway
2006-03-28 14:20:57 +00:00
parent 6d001dc761
commit 746261d8bd
4 changed files with 218 additions and 158 deletions
+3 -49
View File
@@ -37,22 +37,6 @@ static void safe_print( int fd, ... )
va_end( ap );
}
static const char *itoa( unsigned n )
{
static char ret[32];
char *p = ret;
for( int div = 1000000000; div > 0; div /= 10 )
{
*p++ = (n / div) + '0';
n %= div;
}
*p = 0;
p = ret;
while( p[0] == '0' && p[1] )
++p;
return p;
}
#if defined(LINUX)
static void GetExecutableName( char *buf, int bufsize )
{
@@ -218,38 +202,6 @@ static void parent_process( int to_child, const CrashData *crash )
* signal trampolines. The result is that it doesn't properly show the
* function that actually caused the signal--which is the most important
* one! So, we have to do it all ourself. */
const char *SignalName( int signo )
{
#define X(a) case a: return #a;
switch( signo )
{
case SIGALRM: return "Alarm";
case SIGBUS: return "Bus error";
case SIGFPE: return "Floating point exception";
X(SIGHUP)
case SIGILL: return "Illegal instruction";
X(SIGINT)
case SIGPIPE: return "Broken pipe";
case SIGABRT: return "Aborted";
X(SIGQUIT)
case SIGSEGV: return "Segmentation fault";
X(SIGTRAP) X(SIGTERM) X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
#if defined(HAVE_DECL_SIGPWR) && HAVE_DECL_SIGPWR
X(SIGPWR)
#endif
#if defined(HAVE_DECL_SIGUSR1) && HAVE_DECL_SIGUSR1
case SIGUSR1: return "Forced crash";
#endif
default:
{
static char buf[128];
strcpy( buf, "Unknown signal " );
strcat( buf, itoa(signo) );
return buf;
}
}
#undef X
}
static void RunCrashHandler( const CrashData *crash )
{
@@ -335,7 +287,9 @@ static void RunCrashHandler( const CrashData *crash )
close( fds[1] );
int status = 0;
#if !defined(MACOSX)
waitpid( childpid, &status, 0 );
#endif
/* We need to resume threads before continuing, or we may deadlock on _exit(). */
/* XXX: race condition: If two threads are deadlocked on a pair of mutexes, there's
@@ -435,7 +389,7 @@ void CrashHandler::CrashSignalHandler( int signal, siginfo_t *si, const ucontext
BacktraceContext ctx;
GetSignalBacktraceContext( &ctx, uc );
GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, &ctx );
#if defined(HAVE_DECL_SIGUSR1)
#if defined(HAVE_DECL_SIGUSR1) && HAVE_DECL_SIGUSR1
if( signal == SIGUSR1 )
BacktraceAllThreads( crash );
#endif
@@ -58,106 +58,6 @@ static void output_stack_trace( FILE *out, const void **BacktracePointers )
}
}
#if !defined(MACOSX)
const char *SignalCodeName( int signo, int code )
{
switch( code )
{
case SI_USER: return "user signal";
case SI_KERNEL: return "kernel signal";
case SI_QUEUE: return "sigqueue signal";
case SI_TIMER: return "timer expired";
case SI_MESGQ: return "mesgq state changed";
case SI_ASYNCIO: return "async I/O completed";
case SI_SIGIO: return "queued SIGIO";
}
switch( signo )
{
case SIGILL:
switch( code )
{
case ILL_ILLOPC: return "illegal opcode";
case ILL_ILLOPN: return "illegal operand";
case ILL_ILLADR: return "illegal addressing mode";
case ILL_ILLTRP: return "illegal trap";
case ILL_PRVOPC: return "privileged opcode";
case ILL_PRVREG: return "privileged register";
case ILL_COPROC: return "coprocessor error";
case ILL_BADSTK: return "internal stack error";
}
break;
case SIGFPE:
switch( code )
{
case FPE_INTDIV: return "integer divide by zero";
case FPE_INTOVF: return "integer overflow";
case FPE_FLTDIV: return "floating point divide by zero";
case FPE_FLTOVF: return "floating point overflow";
case FPE_FLTUND: return "floating point underflow";
case FPE_FLTRES: return "floating point inexact result";
case FPE_FLTINV: return "floating point invalid operation";
case FPE_FLTSUB: return "subscript out of range";
}
break;
case SIGSEGV:
switch( code )
{
case SEGV_MAPERR: return "address not mapped";
case SEGV_ACCERR: return "invalid permissions";
}
break;
case SIGBUS:
switch( code )
{
case BUS_ADRALN: return "invalid address alignment";
case BUS_ADRERR: return "nonexistent physical address";
case BUS_OBJERR: return "object specific hardware error";
}
break;
case SIGTRAP:
switch( code )
{
case TRAP_BRKPT: return "process breakpoint";
case TRAP_TRACE: return "process trace trap";
}
break;
case SIGCHLD:
switch( code )
{
case CLD_EXITED: return "child has exited";
case CLD_KILLED: return "child was killed";
case CLD_DUMPED: return "child terminated abnormally";
case CLD_TRAPPED: return "traced child has trapped";
case CLD_STOPPED: return "child has stopped";
case CLD_CONTINUED: return "stopped child has continued";
}
break;
case SIGPOLL:
switch( code )
{
case POLL_IN: return "data input available";
case POLL_OUT: return "output buffers available";
case POLL_MSG: return "input message available";
case POLL_ERR: return "i/o error";
case POLL_PRI: return "high priority input available";
case POLL_HUP: return "device disconnected";
}
break;
}
static char buf[128];
sprintf( buf, "Unknown code %i", code );
return buf;
}
#endif
bool child_read( int fd, void *p, int size )
{
char *buf = (char *) p;
@@ -288,13 +188,8 @@ static void child_process()
{
case CrashData::SIGNAL:
{
RString Signal = SignalName( crash.signal );
#if !defined(MACOSX)
reason = ssprintf( "%s - %s", Signal.c_str(), SignalCodeName(crash.signal, crash.si.si_code) );
#else
reason = Signal;
#endif
reason = ssprintf( "%s - %s", SignalName(crash.signal), SignalCodeName(crash.signal, crash.si.si_code) );
/* Linux puts the PID that sent the signal in si_addr for SI_USER. */
if( crash.si.si_code == SI_USER )
{
@@ -348,7 +243,7 @@ static void child_process()
#if defined(MACOSX)
/* Forcibly kill our parent. */
kill( getppid(), SIGKILL );
//kill( getppid(), SIGKILL );
InformUserOfCrash( sCrashInfoPath );
#else
/* stdout may have been inadvertently closed by the crash in the parent;
@@ -0,0 +1,208 @@
#include "global.h"
#include "CrashHandlerInternal.h"
#include <csignal>
const char *itoa( unsigned n )
{
static char ret[32];
char *p = ret;
for( int div = 1000000000; div > 0; div /= 10 )
{
*p++ = (n / div) + '0';
n %= div;
}
*p = 0;
p = ret;
while( p[0] == '0' && p[1] )
++p;
return p;
}
const char *SignalName( int signo )
{
switch( signo )
{
case SIGALRM: return "Alarm";
case SIGBUS: return "Bus error";
case SIGFPE: return "Floating point exception";
case SIGHUP: return "Hangup";
case SIGILL: return "Illegal instruction";
case SIGINT: return "Interrupt";
case SIGPIPE: return "Broken pipe";
case SIGABRT: return "Aborted";
case SIGQUIT: return "Quit";
case SIGSEGV: return "Segmentation fault";
case SIGTRAP: return "Trace trap";
case SIGTERM: return "Termination";
case SIGVTALRM: return "Virtual alarm clock";
case SIGXCPU: return "CPU limit exceeded";
case SIGXFSZ: return "File size limit exceeded";
#if defined(HAVE_DECL_SIGPWR) && HAVE_DECL_SIGPWR
case SIGPWR: return "Power failure restart";
#endif
#if defined(HAVE_DECL_SIGUSR1) && HAVE_DECL_SIGUSR1
case SIGUSR1: return "Forced crash";
#endif
}
static char buf[128];
strcpy( buf, "Unknown signal " );
strcat( buf, itoa(signo) );
return buf;
}
const char *SignalCodeName( int signo, int code )
{
switch( code )
{
case SI_USER: return "user signal";
case SI_QUEUE: return "sigqueue signal";
case SI_TIMER: return "timer expired";
case SI_MESGQ: return "mesgq state changed";
case SI_ASYNCIO: return "async I/O completed";
#if defined(SI_SIGIO)
case SI_SIGIO: return "queued SIGIO";
#endif
#if defined(SI_KERNEL)
case SI_KERNEL: return "kernel signal";
#endif
}
switch( signo )
{
case SIGILL:
switch( code )
{
case ILL_ILLOPC: return "illegal opcode";
case ILL_ILLTRP: return "illegal trap";
case ILL_PRVOPC: return "privileged opcode";
#if defined(ILL_ILLOPN)
case ILL_ILLOPN: return "illegal operand";
#endif
#if defined(ILL_ILLADR)
case ILL_ILLADR: return "illegal addressing mode";
#endif
#if defined(ILL_PRVREG)
case ILL_PRVREG: return "privileged register";
#endif
#if defined(ILL_COPROC)
case ILL_COPROC: return "coprocessor error";
#endif
#if defined(ILL_BADSTK)
case ILL_BADSTK: return "internal stack error";
#endif
}
break;
case SIGFPE:
switch( code )
{
case FPE_FLTDIV: return "floating point divide by zero";
case FPE_FLTOVF: return "floating point overflow";
case FPE_FLTUND: return "floating point underflow";
case FPE_FLTRES: return "floating point inexact result";
case FPE_FLTINV: return "floating point invalid operation";
#if defined(FPE_INTDIV)
case FPE_INTDIV: return "integer divide by zero";
#endif
#if defined(FPE_INTOVF)
case FPE_INTOVF: return "integer overflow";
#endif
#if defined(FPE_FLTSUB)
case FPE_FLTSUB: return "subscript out of range";
#endif
}
break;
case SIGSEGV:
switch( code )
{
case SEGV_MAPERR: return "address not mapped";
case SEGV_ACCERR: return "invalid permissions";
}
break;
case SIGBUS:
switch( code )
{
case BUS_ADRALN: return "invalid address alignment";
#if defined(BUS_ADRERR)
case BUS_ADRERR: return "nonexistent physical address";
#endif
#if defined(BUS_OBJERR)
case BUS_OBJERR: return "object specific hardware error";
#endif
}
break;
case SIGTRAP:
switch( code )
{
#if defined(TRAP_BRKPT)
case TRAP_BRKPT: return "process breakpoint";
#endif
#if defined(TRAP_TRACE)
case TRAP_TRACE: return "process trace trap";
#endif
}
break;
case SIGCHLD:
switch( code )
{
case CLD_EXITED: return "child has exited";
case CLD_KILLED: return "child was killed";
case CLD_DUMPED: return "child terminated abnormally";
case CLD_TRAPPED: return "traced child has trapped";
case CLD_STOPPED: return "child has stopped";
case CLD_CONTINUED: return "stopped child has continued";
}
break;
#if defined(SIGPOLL)
case SIGPOLL:
switch( code )
{
case POLL_IN: return "data input available";
case POLL_OUT: return "output buffers available";
case POLL_MSG: return "input message available";
case POLL_ERR: return "i/o error";
case POLL_PRI: return "high priority input available";
case POLL_HUP: return "device disconnected";
}
break;
#endif
}
static char buf[128];
strcpy( buf, "Unknown code " );
strcat( buf, itoa(code) );
return buf;
}
/*
* (c) 2003-2006 Glenn Maynard, Steve Checkoway
* 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.
*/
@@ -30,12 +30,15 @@ struct CrashData
#define CHILD_MAGIC_PARAMETER "--private-do-crash-handler"
/* These can return a pointer to static memory. Copy the returned string if you wish to save it. */
const char *itoa( unsigned n );
const char *SignalName( int signo );
const char *SignalCodeName( int signo, int code );
#endif
/*
* (c) 2003-2004 Glenn Maynard
* (c) 2003-2006 Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a