Skip to content

Commit

Permalink
Prevented the error handler from breaking compilation on certain plat…
Browse files Browse the repository at this point in the history
…forms.

And fixed a few things like adding header ifdefs/ for pragma once support,
code style fixes, ...
  • Loading branch information
Yohann Ferreira committed Jun 30, 2014
1 parent 3389a54 commit d674c94
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 37 deletions.
39 changes: 25 additions & 14 deletions source/StackTracePrint.cpp
Expand Up @@ -19,10 +19,19 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#if defined (__i386__) | defined (__x86_64__) // Only for supported platforms

#include "StackTracePrint.h"

void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
void StackTracePrint::critErrHandler(int sig_num, siginfo_t * info, void * ucontext)
{
// Prevent running a function that isn't supported on certain platforms.
#if not defined (__i386__) & not defined (__x86_64__)
std::cout << "No error handler supported for this platform" << std::endl;
return;
#endif

void * array[50];
void * caller_address;
sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;
Expand All @@ -36,16 +45,16 @@ void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * uconte
#endif
// void * caller_address = (void *) uc->uc_mcontext.eip; // x86 specific

std::cerr << "signal " << sig_num
<< " (" << strsignal(sig_num) << "), address is "
<< info->si_addr << " from " << caller_address
std::cerr << "signal " << sig_num
<< " (" << strsignal(sig_num) << "), address is "
<< info->si_addr << " from " << caller_address
<< std::endl << std::endl;

int size = backtrace(array, 50);

array[1] = caller_address;

char ** messages = backtrace_symbols(array, size);
char ** messages = backtrace_symbols(array, size);

// skip first stack frame (points here)
for (int i = 1; i < size && messages != NULL; ++i)
Expand All @@ -55,11 +64,11 @@ void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * uconte
// find parantheses and +address offset surrounding mangled name
for (char *p = messages[i]; *p; ++p)
{
if (*p == '(')
if (*p == '(')
{
mangled_name = p;
mangled_name = p;
}
else if (*p == '+')
else if (*p == '+')
{
offset_begin = p;
}
Expand All @@ -71,7 +80,7 @@ void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * uconte
}

// if the line could be processed, attempt to demangle the symbol
if (mangled_name && offset_begin && offset_end &&
if (mangled_name && offset_begin && offset_end &&
mangled_name < offset_begin)
{
*mangled_name++ = '\0';
Expand All @@ -83,17 +92,17 @@ void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * uconte

// if demangling is successful, output the demangled function name
if (status == 0)
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< real_name << "+" << offset_begin << offset_end
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< real_name << "+" << offset_begin << offset_end
<< std::endl;

}
// otherwise, output the mangled function name
else
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< mangled_name << "+" << offset_begin << offset_end
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< mangled_name << "+" << offset_begin << offset_end
<< std::endl;
}
free(real_name);
Expand All @@ -110,3 +119,5 @@ void StackTracePrint::crit_err_hdlr(int sig_num, siginfo_t * info, void * uconte

exit(EXIT_FAILURE);
}

#endif // supported platforms
19 changes: 13 additions & 6 deletions source/StackTracePrint.h
Expand Up @@ -20,6 +20,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __STACKTRACE_H__
#define __STACKTRACE_H__

#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
Expand All @@ -31,18 +34,22 @@
#include <cxxabi.h>
#include <iostream>

namespace StackTracePrint
{

namespace StackTracePrint{

/* This structure mirrors the one found in /usr/include/asm/ucontext.h */
typedef struct _sig_ucontext {
//! \brief This structure mirrors the one found in /usr/include/asm/ucontext.h
typedef struct _sig_ucontext
{
unsigned long uc_flags;
struct ucontext *uc_link;
struct ucontext* uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
} sig_ucontext_t;

void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext);
//! \brief Handles critical error stack trace printing.
void critErrHandler(int sig_num, siginfo_t * info, void * ucontext);

}

#endif // __STACKTRACE_H__
46 changes: 29 additions & 17 deletions source/main.cpp
Expand Up @@ -19,7 +19,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <iostream>
#include <string.h>

Expand All @@ -32,19 +31,38 @@

#include "ODApplication.h"
#include "Socket.h"

#if defined (__i386__) | defined (__x86_64__) // Only for supported platforms

#include "StackTracePrint.h"

//! \brief Init the error hanlder used to get a full stacktrace when crashing
void setErrorHandler()
{
struct sigaction sigact;
sigact.sa_sigaction = StackTracePrint::critErrHandler;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0)
{
std::cerr << "error setting signal handler for: "
<< SIGSEGV << strsignal(SIGSEGV) << std::endl;
exit(EXIT_FAILURE);
}
}
#else
void setErrorHandler()
{
std::cout << "No error handler for this platform" << std::endl;
}
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>


using std::cerr, std::endl;
using namespace StackTracePrint;

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
int main(int argc, char **argv)
int main(int argc, char** argv)
#endif

{
Expand All @@ -55,26 +73,20 @@ int main(int argc, char **argv)

if(WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
{
cerr << "Couldn't not find a usable WinSock DLL.n";
std::cerr << "Couldn't not find a usable WinSock DLL." << std::endl;
exit(1);
}
#endif

struct sigaction sigact;
sigact.sa_sigaction = StackTracePrint::crit_err_hdlr;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0)
{
cerr << "error setting signal handler for " << SIGSEGV << strsignal(SIGSEGV) <<endl;
exit(EXIT_FAILURE);
}
setErrorHandler();

try
{
new ODApplication;
}
catch (Ogre::Exception& e)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox(0, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occurred: %s\n", e.what());
Expand Down

0 comments on commit d674c94

Please sign in to comment.