diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Generating/CompoGen.cpp | 2 | ||||
-rw-r--r-- | src/Generating/FinishGen.cpp | 2 | ||||
-rw-r--r-- | src/Globals.h | 5 | ||||
-rw-r--r-- | src/Noise/Noise.cpp | 1 | ||||
-rw-r--r-- | src/OSSupport/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/OSSupport/StackTrace.cpp | 44 | ||||
-rw-r--r-- | src/OSSupport/StackTrace.h | 15 | ||||
-rw-r--r-- | src/World.cpp | 4 | ||||
-rw-r--r-- | src/World.h | 3 | ||||
-rw-r--r-- | src/main.cpp | 5 |
10 files changed, 80 insertions, 9 deletions
diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 23cc64d78..6c3b50b4e 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -324,7 +324,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc: CeilingDisguise = -CeilingDisguise; } - int CeilingDisguiseHeight = Height - 2 - (int)CeilingDisguise * 3; + int CeilingDisguiseHeight = Height - 2 - FloorC(CeilingDisguise * 3); for (int y = Height - 1; y > CeilingDisguiseHeight; y--) { diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 2ff3e7f67..1e8a67dd0 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -516,7 +516,7 @@ void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) } int Height = a_ChunkDesc.GetHeight(x, z); - if (Height >= cChunkDef::Height) + if (Height >= cChunkDef::Height - 1) { // Too high up continue; diff --git a/src/Globals.h b/src/Globals.h index 582f5fdaa..d75ae0093 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -264,6 +264,7 @@ template class SizeChecker<UInt16, 2>; #include "OSSupport/Thread.h" #include "OSSupport/File.h" #include "Logger.h" + #include "OSSupport/StackTrace.h" #else // Logging functions void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2); @@ -349,14 +350,14 @@ void inline LOGD(const char* a_Format, ...) #else #ifdef _DEBUG - #define ASSERT( x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), assert(0), 0)) + #define ASSERT( x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), PrintStackTrace(), assert(0), 0)) #else #define ASSERT(x) ((void)(x)) #endif #endif // Pretty much the same as ASSERT() but stays in Release builds -#define VERIFY( x) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0)) +#define VERIFY( x) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), PrintStackTrace(), exit(1), 0)) // Same as assert but in all Self test builds #ifdef SELF_TEST diff --git a/src/Noise/Noise.cpp b/src/Noise/Noise.cpp index 509be7d6c..0249ab6c1 100644 --- a/src/Noise/Noise.cpp +++ b/src/Noise/Noise.cpp @@ -2,7 +2,6 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Noise.h" -#include "OSSupport/Timer.h" #define FAST_FLOOR(x) (((x) < 0) ? (((int)x) - 1) : ((int)x)) diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index c3eabeef6..592525941 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -16,8 +16,10 @@ SET (SRCS Sleep.cpp Socket.cpp SocketThreads.cpp + StackTrace.cpp Thread.cpp - Timer.cpp) + Timer.cpp +) SET (HDRS CriticalSection.h @@ -32,8 +34,10 @@ SET (HDRS Sleep.h Socket.h SocketThreads.h + StackTrace.h Thread.h - Timer.h) + Timer.h +) if(NOT MSVC) add_library(OSSupport ${SRCS} ${HDRS}) diff --git a/src/OSSupport/StackTrace.cpp b/src/OSSupport/StackTrace.cpp new file mode 100644 index 000000000..a56568457 --- /dev/null +++ b/src/OSSupport/StackTrace.cpp @@ -0,0 +1,44 @@ + +// StackTrace.cpp + +// Implements the functions to print current stack traces + +#include "Globals.h" +#include "StackTrace.h" +#ifdef _WIN32 + #include "../StackWalker.h" +#else + #include <execinfo.h> + #include <unistd.h> +#endif + + + + + +void PrintStackTrace(void) +{ + #ifdef _WIN32 + // Reuse the StackWalker from the LeakFinder project already bound to MCS + // Define a subclass of the StackWalker that outputs everything to stdout + class PrintingStackWalker : + public StackWalker + { + virtual void OnOutput(LPCSTR szText) override + { + puts(szText); + } + } sw; + sw.ShowCallstack(); + #else + // Use the backtrace() function to get and output the stackTrace: + // Code adapted from http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes + void * stackTrace[30]; + size_t numItems = backtrace(stackTrace, ARRAYCOUNT(stackTrace)); + backtrace_symbols_fd(stackTrace, numItems, STDERR_FILENO); + #endif +} + + + + diff --git a/src/OSSupport/StackTrace.h b/src/OSSupport/StackTrace.h new file mode 100644 index 000000000..228a00077 --- /dev/null +++ b/src/OSSupport/StackTrace.h @@ -0,0 +1,15 @@ + +// StackTrace.h + +// Declares the functions to print current stack trace + + + + + +/** Prints the stacktrace for the current thread. */ +extern void PrintStackTrace(void); + + + + diff --git a/src/World.cpp b/src/World.cpp index 0dec0bd96..5fe64ea3a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -164,6 +164,8 @@ protected: if (m_NumPrepared >= m_MaxIdx) { m_EvtFinished.Set(); + // Must return here, because "this" may have gotten deleted by the previous line + return; } // Queue another chunk, if appropriate: @@ -2678,7 +2680,7 @@ bool cWorld::ForEachPlayer(cPlayerListCallback & a_Callback) bool cWorld::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback) { - // Calls the callback for each player in the list + // Calls the callback for the specified player in the list cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { diff --git a/src/World.h b/src/World.h index 68d0654ee..31bc9dad6 100644 --- a/src/World.h +++ b/src/World.h @@ -315,7 +315,8 @@ public: /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS << - /** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. Callback return ignored */ + /** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. + Callback return value is ignored. If there are multiple players of the same name, only (random) one is processed by the callback. */ bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Finds a player from a partial or complete player name and calls the callback - case-insensitive */ diff --git a/src/main.cpp b/src/main.cpp index c60e13a8c..fe4b360a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,6 +61,7 @@ void NonCtrlHandler(int a_Signal) std::signal(SIGSEGV, SIG_DFL); LOGERROR(" D: | MCServer has encountered an error and needs to close"); LOGERROR("Details | SIGSEGV: Segmentation fault"); + PrintStackTrace(); abort(); } case SIGABRT: @@ -71,6 +72,7 @@ void NonCtrlHandler(int a_Signal) std::signal(a_Signal, SIG_DFL); LOGERROR(" D: | MCServer has encountered an error and needs to close"); LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault"); + PrintStackTrace(); abort(); } case SIGINT: @@ -137,6 +139,9 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except g_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, g_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); CloseHandle(dumpFile); + // Print the stack trace for the basic debugging: + PrintStackTrace(); + // Revert to old stack: _asm { |