From 746261d8bd4280e8a4a7efb33671351c39810557 Mon Sep 17 00:00:00 2001 From: Steve Checkoway Date: Tue, 28 Mar 2006 14:20:57 +0000 Subject: [PATCH] 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. --- stepmania/src/archutils/Unix/CrashHandler.cpp | 52 +---- .../src/archutils/Unix/CrashHandlerChild.cpp | 111 +--------- .../archutils/Unix/CrashHandlerInternal.cpp | 208 ++++++++++++++++++ .../src/archutils/Unix/CrashHandlerInternal.h | 5 +- 4 files changed, 218 insertions(+), 158 deletions(-) create mode 100644 stepmania/src/archutils/Unix/CrashHandlerInternal.cpp diff --git a/stepmania/src/archutils/Unix/CrashHandler.cpp b/stepmania/src/archutils/Unix/CrashHandler.cpp index 6a3370c4c9..e0511cf8e6 100644 --- a/stepmania/src/archutils/Unix/CrashHandler.cpp +++ b/stepmania/src/archutils/Unix/CrashHandler.cpp @@ -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 diff --git a/stepmania/src/archutils/Unix/CrashHandlerChild.cpp b/stepmania/src/archutils/Unix/CrashHandlerChild.cpp index 4b303b9db6..ef5a7e1df3 100644 --- a/stepmania/src/archutils/Unix/CrashHandlerChild.cpp +++ b/stepmania/src/archutils/Unix/CrashHandlerChild.cpp @@ -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 "non‐existent 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; diff --git a/stepmania/src/archutils/Unix/CrashHandlerInternal.cpp b/stepmania/src/archutils/Unix/CrashHandlerInternal.cpp new file mode 100644 index 0000000000..08cb537f03 --- /dev/null +++ b/stepmania/src/archutils/Unix/CrashHandlerInternal.cpp @@ -0,0 +1,208 @@ +#include "global.h" +#include "CrashHandlerInternal.h" + +#include + +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. + */ + diff --git a/stepmania/src/archutils/Unix/CrashHandlerInternal.h b/stepmania/src/archutils/Unix/CrashHandlerInternal.h index 650316cd5b..cd7179e367 100644 --- a/stepmania/src/archutils/Unix/CrashHandlerInternal.h +++ b/stepmania/src/archutils/Unix/CrashHandlerInternal.h @@ -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