2012-01-29 11:28:19 -08:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2011-10-03 11:41:19 -07:00
# include "cRoot.h"
2011-10-21 17:15:12 -07:00
# include <exception> //std::exception
# include <csignal> //std::signal
# include <stdlib.h> //exit()
2012-02-21 13:09:42 -08:00
# ifdef _WIN32
# include <dbghelp.h>
# endif // _WIN32
2011-11-07 17:25:01 -08:00
# include "SquirrelBindings.h"
# if USE_SQUIRREL
2012-02-16 05:42:35 -08:00
# pragma warning(push)
2012-01-29 11:28:19 -08:00
# pragma warning(disable:4100;disable:4127;disable:4510;disable:4610;disable:4244;disable:4512) // Getting A LOT of these warnings from SqPlus
# include <sqplus/sqplus.h>
2012-02-16 05:42:35 -08:00
# pragma warning(pop)
2011-11-07 17:25:01 -08:00
# endif
2012-01-29 11:28:19 -08:00
2012-02-13 13:47:03 -08:00
/// If defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window
# define ENABLE_LEAK_FINDER
# if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
# define XML_LEAK_FINDER
2012-02-16 05:42:35 -08:00
# pragma warning(push)
# pragma warning(disable:4100)
2012-02-13 13:47:03 -08:00
# include "LeakFinder.h"
2012-02-16 05:42:35 -08:00
# pragma warning(pop)
2012-02-13 13:47:03 -08:00
# endif
2012-01-29 11:28:19 -08:00
2011-10-21 17:15:12 -07:00
void ShowCrashReport ( int )
{
std : : signal ( SIGSEGV , SIG_DFL ) ;
printf ( " \n \n MCServer has crashed! \n " ) ;
exit ( - 1 ) ;
}
2011-10-03 11:41:19 -07:00
2012-02-13 13:47:03 -08:00
2012-02-22 00:06:56 -08:00
# if defined(_WIN32) && !defined(_WIN64)
2012-02-21 13:09:42 -08:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2012-02-22 00:06:56 -08:00
// Windows 32-bit stuff: when the server crashes, create a "dump file" containing the callstack of each thread and some variables; let the user send us that crash file for analysis
2012-02-21 13:09:42 -08:00
typedef BOOL ( WINAPI * pMiniDumpWriteDump ) (
HANDLE hProcess ,
DWORD ProcessId ,
HANDLE hFile ,
MINIDUMP_TYPE DumpType ,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam ,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam ,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
) ;
pMiniDumpWriteDump g_WriteMiniDump ; // The function in dbghlp DLL that creates dump files
char g_DumpFileName [ MAX_PATH ] ; // Filename of the dump file; hes to be created before the dump handler kicks in
char g_ExceptionStack [ 128 * 1024 ] ; // Substitute stack, just in case the handler kicks in because of "insufficient stack space"
2012-02-23 03:37:53 -08:00
MINIDUMP_TYPE g_DumpFlags = MiniDumpNormal ; // By default dump only the stack and some helpers
2012-02-21 13:09:42 -08:00
/** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar.
Its purpose is to create the crashdump using the dbghlp DLLs
*/
LONG WINAPI LastChanceExceptionFilter ( __in struct _EXCEPTION_POINTERS * a_ExceptionInfo )
{
char * newStack = & g_ExceptionStack [ sizeof ( g_ExceptionStack ) ] ;
char * oldStack ;
// Use the substitute stack:
2012-02-22 00:06:56 -08:00
// This code is the reason why we don't support 64-bit (yet)
2012-02-21 13:09:42 -08:00
_asm
{
mov oldStack , esp
mov esp , newStack
}
MINIDUMP_EXCEPTION_INFORMATION ExcInformation ;
ExcInformation . ThreadId = GetCurrentThreadId ( ) ;
ExcInformation . ExceptionPointers = a_ExceptionInfo ;
ExcInformation . ClientPointers = 0 ;
// Write the dump file:
HANDLE dumpFile = CreateFile ( g_DumpFileName , GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL ) ;
2012-02-23 03:37:53 -08:00
g_WriteMiniDump ( GetCurrentProcess ( ) , GetCurrentProcessId ( ) , dumpFile , g_DumpFlags , ( a_ExceptionInfo ) ? & ExcInformation : NULL , NULL , NULL ) ;
2012-02-21 13:09:42 -08:00
CloseHandle ( dumpFile ) ;
// Revert to old stack:
_asm
{
mov esp , oldStack
}
return 0 ;
}
2012-02-22 00:06:56 -08:00
# endif // _WIN32 && !_WIN64
2012-02-21 13:09:42 -08:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// main:
2011-10-03 11:41:19 -07:00
int main ( int argc , char * * argv )
{
( void ) argc ;
( void ) argv ;
2012-02-13 13:47:03 -08:00
# if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
InitLeakFinder ( ) ;
# endif
2012-02-21 13:09:42 -08:00
// Magic code to produce dump-files on Windows if the server crashes:
2012-02-22 00:06:56 -08:00
# if defined(_WIN32) && !defined(_WIN64)
2012-02-21 13:09:42 -08:00
HINSTANCE hDbgHelp = LoadLibrary ( " DBGHELP.DLL " ) ;
g_WriteMiniDump = ( pMiniDumpWriteDump ) GetProcAddress ( hDbgHelp , " MiniDumpWriteDump " ) ;
if ( g_WriteMiniDump ! = NULL )
{
_snprintf_s ( g_DumpFileName , ARRAYCOUNT ( g_DumpFileName ) , _TRUNCATE , " crash_mcs_%x.dmp " , GetCurrentProcessId ( ) ) ;
SetUnhandledExceptionFilter ( LastChanceExceptionFilter ) ;
2012-02-23 03:37:53 -08:00
// Parse arguments for minidump flags:
for ( int i = 0 ; i < argc ; i + + )
{
if ( stricmp ( argv [ i ] , " /cdg " ) = = 0 )
{
// Add globals to the dump
g_DumpFlags = ( MINIDUMP_TYPE ) ( g_DumpFlags | MiniDumpWithDataSegs ) ;
}
else if ( stricmp ( argv [ i ] , " /cdf " ) = = 0 )
{
// Add full memory to the dump (HUUUGE file)
g_DumpFlags = ( MINIDUMP_TYPE ) ( g_DumpFlags | MiniDumpWithFullMemory ) ;
}
} // for i - argv[]
2012-02-21 13:09:42 -08:00
}
2012-02-22 00:06:56 -08:00
# endif // _WIN32 && !_WIN64
2012-02-21 13:09:42 -08:00
// End of dump-file magic
2012-03-09 01:39:48 -08:00
# if defined(_DEBUG) && defined(_MSC_VER)
2011-10-03 11:41:19 -07:00
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) ;
2012-02-13 13:47:03 -08:00
// _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
// Only useful when the leak is in the same sequence all the time
// _CrtSetBreakAlloc(85950);
2012-03-09 01:39:48 -08:00
# endif // _DEBUG && _MSC_VER
2012-02-13 13:47:03 -08:00
# ifndef _DEBUG
2011-10-21 17:15:12 -07:00
std : : signal ( SIGSEGV , ShowCrashReport ) ;
2012-02-13 13:47:03 -08:00
# endif
2011-10-21 17:15:12 -07:00
2012-02-21 13:09:42 -08:00
// DEBUG: test the dumpfile creation:
// *((int *)0) = 0;
2011-10-03 11:41:19 -07:00
try
{
2011-10-21 17:15:12 -07:00
cRoot Root ;
2011-10-03 11:41:19 -07:00
Root . Start ( ) ;
}
catch ( std : : exception & e )
{
LOGERROR ( " Standard exception: %s " , e . what ( ) ) ;
}
catch ( . . . )
{
LOGERROR ( " Unknown exception! " ) ;
}
2011-11-07 17:25:01 -08:00
2012-02-13 13:47:03 -08:00
# if USE_SQUIRREL
2011-11-07 17:25:01 -08:00
SquirrelVM : : Shutdown ( ) ;
2012-02-13 13:47:03 -08:00
# endif
2011-11-07 17:25:01 -08:00
2012-02-13 13:47:03 -08:00
# if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
DeinitLeakFinder ( ) ;
# endif
2011-10-03 11:41:19 -07:00
return 0 ;
}
2012-02-13 13:47:03 -08:00