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