From fa64103aa87a8f0f2a3351bb4a54e93e8ade1082 Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Mon, 27 Dec 2010 14:34:17 +0200
Subject: [PATCH] better debug output in segfaults and stack overflows in
 windows

---
 minetest.vcproj    |  1 +
 src/client.cpp     | 34 ++++++++-----------------
 src/debug.cpp      | 30 ++++++++++++++++++++++
 src/debug.h        | 63 ++++++++++++++++++++++++++++++++++++++++++++++
 src/main.cpp       | 45 +++++++++++++--------------------
 src/mapblock.cpp   |  5 ++++
 src/materials.h    |  1 -
 src/server.cpp     | 34 ++++++-------------------
 src/servermain.cpp | 15 +++--------
 9 files changed, 138 insertions(+), 90 deletions(-)

diff --git a/minetest.vcproj b/minetest.vcproj
index 45d6027dd..c244b4370 100644
--- a/minetest.vcproj
+++ b/minetest.vcproj
@@ -119,6 +119,7 @@
 				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;&quot;..\jthread\jthread-1.2.1\src&quot;;&quot;..\irrlicht\irrlicht-1.7.1\include&quot;;&quot;..\zlib\zlib-1.2.5&quot;"
 				PreprocessorDefinitions="WIN32;_HAS_ITERATOR_DEBUGGING=0,UNITTEST_DISABLE,_CRT_SECURE_NO_DEPRECATE"
+				ExceptionHandling="2"
 				BufferSecurityCheck="false"
 				EnableEnhancedInstructionSet="1"
 				FloatingPointModel="2"
diff --git a/src/client.cpp b/src/client.cpp
index af2b375f4..4792490f9 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -31,34 +31,22 @@ void * ClientUpdateThread::Thread()
 	ThreadStarted();
 
 	DSTACK(__FUNCTION_NAME);
-
-#if CATCH_UNHANDLED_EXCEPTIONS
-	try
+	
+	BEGIN_DEBUG_EXCEPTION_HANDLER
+	
+	while(getRun())
 	{
-#endif
-		while(getRun())
-		{
-			m_client->asyncStep();
+		m_client->asyncStep();
 
-			//m_client->updateSomeExpiredMeshes();
+		//m_client->updateSomeExpiredMeshes();
 
-			bool was = m_client->AsyncProcessData();
+		bool was = m_client->AsyncProcessData();
 
-			if(was == false)
-				sleep_ms(10);
-		}
-#if CATCH_UNHANDLED_EXCEPTIONS
+		if(was == false)
+			sleep_ms(10);
 	}
-	/*
-		This is what has to be done in threads to get suitable debug info
-	*/
-	catch(std::exception &e)
-	{
-		dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
-				<<e.what()<<std::endl;
-		assert(0);
-	}
-#endif
+
+	END_DEBUG_EXCEPTION_HANDLER
 
 	return NULL;
 }
diff --git a/src/debug.cpp b/src/debug.cpp
index df8cbeb22..9fbdf7a39 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -194,3 +194,33 @@ DebugStacker::~DebugStacker()
 	}
 }
 
+
+#ifdef _WIN32
+void se_trans_func(unsigned int u, EXCEPTION_POINTERS* pExp)
+{
+	dstream<<"In trans_func.\n";
+	if(u == EXCEPTION_ACCESS_VIOLATION)
+	{
+		PEXCEPTION_RECORD r = pExp->ExceptionRecord;
+		dstream<<"Access violation at "<<r->ExceptionAddress
+				<<" write?="<<r->ExceptionInformation[0]
+				<<" address="<<r->ExceptionInformation[1]
+				<<std::endl;
+		throw FatalSystemException
+		("Access violation");
+	}
+	if(u == EXCEPTION_STACK_OVERFLOW)
+	{
+		throw FatalSystemException
+		("Stack overflow");
+	}
+	if(u == EXCEPTION_ILLEGAL_INSTRUCTION)
+	{
+		throw FatalSystemException
+		("Illegal instruction");
+	}
+}
+#endif
+
+
+
diff --git a/src/debug.h b/src/debug.h
index 3f269176a..8faa65eb8 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -27,6 +27,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "common_irrlicht.h"
 #include "threads.h"
 #include "gettime.h"
+#include "constants.h"
+#include "exceptions.h"
+
+#ifdef _WIN32
+	#define WIN32_LEAN_AND_MEAN
+	#include <windows.h>
+	#include <eh.h>
+#else
+#endif
 
 /*
 	Debug output
@@ -215,6 +224,60 @@ class PacketCounter
 	core::map<u16, u16> m_packets;
 };
 
+/*
+	These should be put into every thread
+*/
+
+#if CATCH_UNHANDLED_EXCEPTIONS == 1
+	#define BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER try{
+	#define END_PORTABLE_DEBUG_EXCEPTION_HANDLER\
+		}catch(std::exception &e){\
+			dstream<<std::endl<<DTIME\
+					<<"ERROR: An unhandled exception occurred: "\
+					<<e.what()<<std::endl;\
+			assert(0);\
+		}
+	#ifdef _WIN32 // Windows
+
+/*class SE_Exception : public std::exception
+{
+private:
+    unsigned int nSE;
+public:
+    SE_Exception() {}
+    SE_Exception( unsigned int n ) : nSE( n ) {}
+    ~SE_Exception() {}
+    unsigned int getSeNumber() { return nSE; }
+};*/
+
+void se_trans_func(unsigned int, EXCEPTION_POINTERS*);
+
+class FatalSystemException : public BaseException
+{
+public:
+	FatalSystemException(const char *s):
+		BaseException(s)
+	{}
+};
+
+		#define BEGIN_DEBUG_EXCEPTION_HANDLER \
+			BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER\
+			_set_se_translator(se_trans_func);
+
+		#define END_DEBUG_EXCEPTION_HANDLER \
+			END_PORTABLE_DEBUG_EXCEPTION_HANDLER
+
+	#else // Posix
+		#define BEGIN_DEBUG_EXCEPTION_HANDLER\
+			BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER
+		#define END_DEBUG_EXCEPTION_HANDLER\
+			END_PORTABLE_DEBUG_EXCEPTION_HANDLER
+	#endif
+#else
+	// Dummy ones
+	#define BEGIN_DEBUG_EXCEPTION_HANDLER
+	#define END_DEBUG_EXCEPTION_HANDLER
+#endif
 
 #endif // DEBUG_HEADER
 
diff --git a/src/main.cpp b/src/main.cpp
index bd0ebd8ca..f9022de64 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -135,6 +135,13 @@ TODO: Make fetching sector's blocks more efficient when rendering
 
 TODO: Make the video backend selectable
 
+TODO: Copy the text of the last picked sign to inventory in creative
+      mode
+
+TODO: Get rid of GotSplitPacketException
+
+TODO: Check what goes wrong with caching map to disk (Kray)
+
 Block object server side:
       - A "near blocks" buffer, in which some nearby blocks are stored.
 	  - For all blocks in the buffer, objects are stepped(). This
@@ -146,17 +153,6 @@ Block object server side:
 	    - TODO: For incoming blocks, time difference is calculated and
 	      objects are stepped according to it.
 
-TODO: Copy the text of the last picked sign to inventory in creative
-      mode
-
-TODO: Get rid of GotSplitPacketException
-
-TODO: Check what goes wrong with caching map to disk (Kray)
-
-TODO: Remove LazyMeshUpdater. It is not used as supposed.
-
-TODO: TOSERVER_LEAVE
-
 TODO: Better handling of objects and mobs
       - Scripting?
       - There has to be some way to do it with less spaghetti code
@@ -171,6 +167,7 @@ TODO: Draw big amounts of torches better (that is, throw them in the
 
 TODO: Check if the usage of Client::isFetchingBlocks() in
       updateViewingRange() actually does something
+	  NOTE: It isn't used anymore after the rewrite.
 
 TODO: Make an option to the server to disable building and digging near
       the starting position
@@ -181,14 +178,13 @@ SUGG: Signs could be done in the same way as torches. For this, blocks
 TODO: There has to be some better way to handle static objects than to
       send them all the time. This affects signs and item objects.
 
-Doing now:
-======================================================================
-
 TODO: When server sees that client is removing an inexistent block or
       adding a block to an existent position, resend the MapBlock.
 
-TODO: Fix viewing range updater's oscillation when there is large non-
-      linearity in range-speed relation
+TODO: Map generator: add other materials underground (mud)
+
+Doing now:
+======================================================================
 
 ======================================================================
 
@@ -1095,6 +1091,8 @@ int main(int argc, char *argv[])
 	
 	initializeMaterialProperties();
 
+	BEGIN_DEBUG_EXCEPTION_HANDLER
+
 	try
 	{
 	
@@ -1407,7 +1405,7 @@ int main(int argc, char *argv[])
 	/*
 		This changes the minimum allowed number of vertices in a VBO
 	*/
-	//driver->setMinHardwareBufferVertexCount(1);
+	//driver->setMinHardwareBufferVertexCount(50);
 
 	scene::ISceneManager* smgr = device->getSceneManager();
 	
@@ -2606,18 +2604,9 @@ int main(int argc, char *argv[])
 			menu->drop();
 		}*/
 	}
-#if CATCH_UNHANDLED_EXCEPTIONS
-	/*
-		This is what has to be done in every thread to get suitable debug info
-	*/
-	catch(std::exception &e)
-	{
-		dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
-				<<e.what()<<std::endl;
-		assert(0);
-	}
-#endif
 
+	END_DEBUG_EXCEPTION_HANDLER
+	
 	debugstreams_deinit();
 	
 	return 0;
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index 202877322..e82818396 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -275,6 +275,10 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
 */
 TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
 {
+	// DEBUG
+	u16 *ptr = NULL;
+	*ptr = 7357;
+
 	TileSpec spec;
 
 	/*//DEBUG
@@ -688,6 +692,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
 		collector.fillMesh(mesh_new);
 
 		// Use VBO for mesh (this just would set this for ever buffer)
+		// This will lead to infinite memory usage because or irrlicht.
 		//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
 		
 		/*std::cout<<"MapBlock has "<<fastfaces_new->getSize()<<" faces "
diff --git a/src/materials.h b/src/materials.h
index ae2deac88..422149753 100644
--- a/src/materials.h
+++ b/src/materials.h
@@ -54,7 +54,6 @@ class MaterialProperties
 public:
 	MaterialProperties()
 	{
-		dstream<<__FUNCTION_NAME<<std::endl;
 	}
 
 	void setDiggingProperties(const std::string toolname,
diff --git a/src/server.cpp b/src/server.cpp
index cbe2b932f..05ef13d93 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -40,6 +40,8 @@ void * ServerThread::Thread()
 
 	DSTACK(__FUNCTION_NAME);
 
+	BEGIN_DEBUG_EXCEPTION_HANDLER
+
 	while(getRun())
 	{
 		try{
@@ -51,19 +53,9 @@ void * ServerThread::Thread()
 		catch(con::NoIncomingDataException &e)
 		{
 		}
-#if CATCH_UNHANDLED_EXCEPTIONS
-		/*
-			This is what has to be done in threads to get suitable debug info
-		*/
-		catch(std::exception &e)
-		{
-			dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
-					<<e.what()<<std::endl;
-			assert(0);
-		}
-#endif
 	}
 	
+	END_DEBUG_EXCEPTION_HANDLER
 
 	return NULL;
 }
@@ -75,11 +67,9 @@ void * EmergeThread::Thread()
 	DSTACK(__FUNCTION_NAME);
 
 	bool debug=false;
-#if CATCH_UNHANDLED_EXCEPTIONS
-	try
-	{
-#endif
 	
+	BEGIN_DEBUG_EXCEPTION_HANDLER
+
 	/*
 		Get block info from queue, emerge them and send them
 		to clients.
@@ -267,18 +257,8 @@ void * EmergeThread::Thread()
 		}
 		
 	}
-#if CATCH_UNHANDLED_EXCEPTIONS
-	}//try
-	/*
-		This is what has to be done in threads to get suitable debug info
-	*/
-	catch(std::exception &e)
-	{
-		dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
-				<<e.what()<<std::endl;
-		assert(0);
-	}
-#endif
+
+	END_DEBUG_EXCEPTION_HANDLER
 
 	return NULL;
 }
diff --git a/src/servermain.cpp b/src/servermain.cpp
index 594f7f4a2..01919a7df 100644
--- a/src/servermain.cpp
+++ b/src/servermain.cpp
@@ -125,6 +125,8 @@ int main(int argc, char *argv[])
 
 	initializeMaterialProperties();
 
+	BEGIN_DEBUG_EXCEPTION_HANDLER
+
 	try
 	{
 	
@@ -345,17 +347,8 @@ int main(int argc, char *argv[])
 	{
 		dstream<<DTIME<<"Connection timed out."<<std::endl;
 	}
-#if CATCH_UNHANDLED_EXCEPTIONS
-	/*
-		This is what has to be done in every thread to get suitable debug info
-	*/
-	catch(std::exception &e)
-	{
-		dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
-				<<e.what()<<std::endl;
-		assert(0);
-	}
-#endif
+
+	END_DEBUG_EXCEPTION_HANDLER
 
 	debugstreams_deinit();
 	
-- 
GitLab