SourceMod will now spit out errors for scripts that become corrupt and would otherwise be crashing Core. if you get these errors contact the dev team.
authorDavid Anderson <dvander@alliedmods.net>
Wed Aug 15 20:18:15 2007 +0000 (2007-08-15)
changeset 133902e8f2c0f8af
parent 1338 1ba17552b7b1
child 1340 031de7d14eca
SourceMod will now spit out errors for scripts that become corrupt and would otherwise be crashing Core. if you get these errors contact the dev team.
core/DebugReporter.cpp
core/DebugReporter.h
core/systems/ForwardSys.cpp
core/vm/sp_vm_basecontext.cpp
core/vm/sp_vm_function.cpp
core/vm/sp_vm_function.h
     1.1 --- a/core/DebugReporter.cpp	Wed Aug 15 18:26:15 2007 +0000
     1.2 +++ b/core/DebugReporter.cpp	Wed Aug 15 20:18:15 2007 +0000
     1.3 @@ -75,12 +75,51 @@
     1.4  			sp_public_t *function;
     1.5  			if (ctx->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
     1.6  			{
     1.7 -				g_Logger.LogError("[SM] Unable to call function \"%s\" due to above errors.", function->name);
     1.8 +				g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
     1.9  			}
    1.10  		}
    1.11  	}
    1.12  }
    1.13  
    1.14 +void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr, int err, const char *message, ...)
    1.15 +{
    1.16 +	va_list ap;
    1.17 +	char buffer[512];
    1.18 +
    1.19 +	va_start(ap, message);
    1.20 +	UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
    1.21 +	va_end(ap);
    1.22 +
    1.23 +	const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
    1.24 +	const char *error = GetSourcePawnErrorMessage(err);
    1.25 +
    1.26 +	if (error)
    1.27 +	{
    1.28 +		g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
    1.29 +	} else {
    1.30 +		g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
    1.31 +	}
    1.32 +
    1.33 +	g_Logger.LogError("[SM] %s", buffer);
    1.34 +
    1.35 +	IPluginDebugInfo *pDebug;
    1.36 +	if ((pDebug = pContext->GetDebugInfo()) == NULL)
    1.37 +	{
    1.38 +		g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
    1.39 +		g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
    1.40 +			_GetPluginIndex(pContext));
    1.41 +		return;
    1.42 +	}
    1.43 +
    1.44 +	const char *name;
    1.45 +	if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
    1.46 +	{
    1.47 +		g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
    1.48 +	} else {
    1.49 +		g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
    1.50 +	}
    1.51 +}
    1.52 +
    1.53  void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
    1.54  {
    1.55  	const char *lastname;
     2.1 --- a/core/DebugReporter.h	Wed Aug 15 18:26:15 2007 +0000
     2.2 +++ b/core/DebugReporter.h	Wed Aug 15 20:18:15 2007 +0000
     2.3 @@ -44,6 +44,7 @@
     2.4  public: // IDebugListener
     2.5  	void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
     2.6  	void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
     2.7 +	void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
     2.8  private:
     2.9  	int _GetPluginIndex(IPluginContext *ctx);
    2.10  };
     3.1 --- a/core/systems/ForwardSys.cpp	Wed Aug 15 18:26:15 2007 +0000
     3.2 +++ b/core/systems/ForwardSys.cpp	Wed Aug 15 20:18:15 2007 +0000
     3.3 @@ -35,6 +35,7 @@
     3.4  #include "ForwardSys.h"
     3.5  #include "PluginSys.h"
     3.6  #include "ShareSys.h"
     3.7 +#include "DebugReporter.h"
     3.8  
     3.9  CForwardManager g_Forwards;
    3.10  
    3.11 @@ -308,6 +309,7 @@
    3.12  
    3.13  		for (unsigned int i=0; i<num_params; i++)
    3.14  		{
    3.15 +			int err = SP_ERROR_PARAM;
    3.16  			param = &temp_info[i];
    3.17  			if (i >= m_numparams || m_types[i] == Param_Any)
    3.18  			{
    3.19 @@ -322,31 +324,37 @@
    3.20  				 */
    3.21  				if (type == Param_String)
    3.22  				{
    3.23 -					func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
    3.24 +					err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
    3.25  				} else if (type == Param_Float || type == Param_Cell) {
    3.26 -					func->PushCellByRef(&param->val); 
    3.27 +					err = func->PushCellByRef(&param->val); 
    3.28  				} else {
    3.29 -					func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
    3.30 +					err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
    3.31  					assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
    3.32  				}
    3.33  			} else {
    3.34  				/* If we're not byref or not vararg, our job is a bit easier. */
    3.35  				assert(type == Param_Cell || type == Param_Float);
    3.36 -				func->PushCell(param->val);
    3.37 +				err = func->PushCell(param->val);
    3.38 +			}
    3.39 +			if (err != SP_ERROR_NONE)
    3.40 +			{
    3.41 +				if (!filter || !filter->OnErrorReport(this, func, err))
    3.42 +				{
    3.43 +					g_DbgReporter.GenerateError(func->GetParentContext(), 
    3.44 +						func->GetFunctionID(), 
    3.45 +						err, 
    3.46 +						"Failed to push parameter while executing forward");
    3.47 +				}
    3.48 +				continue;
    3.49  			}
    3.50  		}
    3.51  		
    3.52  		/* Call the function and deal with the return value. */
    3.53  		if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
    3.54  		{
    3.55 -			bool handled = false;
    3.56  			if (filter)
    3.57  			{
    3.58 -				handled = filter->OnErrorReport(this, func, err);
    3.59 -			}
    3.60 -			if (!handled)
    3.61 -			{
    3.62 -				/* :TODO: invoke global error reporting here */
    3.63 +				filter->OnErrorReport(this, func, err);
    3.64  			}
    3.65  			failed++;
    3.66  		} else {
     4.1 --- a/core/vm/sp_vm_basecontext.cpp	Wed Aug 15 18:26:15 2007 +0000
     4.2 +++ b/core/vm/sp_vm_basecontext.cpp	Wed Aug 15 20:18:15 2007 +0000
     4.3 @@ -39,6 +39,7 @@
     4.4  
     4.5  #ifdef SOURCEMOD_BUILD
     4.6  #include "Logger.h"
     4.7 +#include "DebugReporter.h"
     4.8  #endif
     4.9  
    4.10  using namespace SourcePawn;
    4.11 @@ -149,7 +150,7 @@
    4.12  			{
    4.13  				continue;
    4.14  			}
    4.15 -			m_pub_funcs[i]->Set(pub->code_offs, this);
    4.16 +			m_pub_funcs[i]->Set(pub->code_offs, this, pub->funcid);
    4.17  		}
    4.18  	}
    4.19  
    4.20 @@ -221,6 +222,10 @@
    4.21  
    4.22  IPluginDebugInfo *BaseContext::GetDebugInfo()
    4.23  {
    4.24 +	if (!IsDebugging())
    4.25 +	{
    4.26 +		return NULL;
    4.27 +	}
    4.28  	return this;
    4.29  }
    4.30  
    4.31 @@ -243,7 +248,13 @@
    4.32  	uint32_t pushcount = ctx->pushcount;
    4.33  	int err;
    4.34  
    4.35 -	PushCell(pushcount++);
    4.36 +	if ((err = PushCell(pushcount++)) != SP_ERROR_NONE)
    4.37 +	{
    4.38 +#if defined SOURCEMOD_BUILD
    4.39 +		g_DbgReporter.GenerateCodeError(this, code_addr, err, "Stack error; cannot complete execution!");
    4.40 +#endif
    4.41 +		return SP_ERROR_NOT_RUNNABLE;
    4.42 +	}
    4.43  	ctx->pushcount = 0;
    4.44  
    4.45  	cell_t save_sp = ctx->sp;
    4.46 @@ -271,26 +282,30 @@
    4.47  	 */
    4.48  	g_SourcePawn.PopTracer(err, m_CustomMsg ? m_MsgCache : NULL);
    4.49  
    4.50 -#if 1//defined _DEBUG
    4.51 -	//:TODO: debug code for leak detection, remove before the release?
    4.52 +#if defined SOURCEMOD_BUILD
    4.53  	if (err == SP_ERROR_NONE)
    4.54  	{
    4.55  		if ((ctx->sp - (cell_t)(pushcount * sizeof(cell_t))) != save_sp)
    4.56  		{
    4.57 -			const char *name;
    4.58 -			ctx->context->GetDebugInfo()->LookupFunction(code_addr, &name);
    4.59 -			g_Logger.LogError("Stack leak detected: sp:%d should be %d on function %s", ctx->sp, save_sp, name);
    4.60 +			g_DbgReporter.GenerateCodeError(this,
    4.61 +				code_addr,
    4.62 +				SP_ERROR_STACKLEAK,
    4.63 +				"Stack leak detected: sp:%d should be %d!",
    4.64 +				ctx->sp,
    4.65 +				save_sp);
    4.66  		}
    4.67  		if (ctx->hp != save_hp)
    4.68  		{
    4.69 -			const char *name;
    4.70 -			ctx->context->GetDebugInfo()->LookupFunction(code_addr, &name);
    4.71 -			g_Logger.LogError("Heap leak detected: hp:%d should be %d on function %s", ctx->hp, save_hp, name);
    4.72 +			g_DbgReporter.GenerateCodeError(this,
    4.73 +				code_addr,
    4.74 +				SP_ERROR_HEAPLEAK,
    4.75 +				"Heap leak detected: sp:%d should be %d!",
    4.76 +				ctx->hp,
    4.77 +				save_hp);
    4.78  		}
    4.79 -		//assert(ctx->sp - pushcount * sizeof(cell_t) == save_sp);
    4.80 -		//assert(ctx->hp == save_hp);
    4.81  	}
    4.82  #endif
    4.83 +
    4.84  	if (err != SP_ERROR_NONE)
    4.85  	{
    4.86  		ctx->sp = save_sp;
    4.87 @@ -958,10 +973,10 @@
    4.88  		pFunc = m_pub_funcs[func_id];
    4.89  		if (!pFunc)
    4.90  		{
    4.91 -			m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs, this);
    4.92 +			m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs, this, ctx->publics[func_id].funcid);
    4.93  			pFunc = m_pub_funcs[func_id];
    4.94  		} else if (pFunc->IsInvalidated()) {
    4.95 -			pFunc->Set(ctx->publics[func_id].code_offs, this);
    4.96 +			pFunc->Set(ctx->publics[func_id].code_offs, this, ctx->publics[func_id].funcid);
    4.97  		}
    4.98  	} else {
    4.99  		/* :TODO: currently not used */
   4.100 @@ -1001,7 +1016,7 @@
   4.101  		GetPublicByIndex(index, &pub);
   4.102  		if (pub)
   4.103  		{
   4.104 -			m_pub_funcs[index] = new CFunction(pub->code_offs, this);
   4.105 +			m_pub_funcs[index] = new CFunction(pub->code_offs, this, pub->funcid);
   4.106  		}
   4.107  		pFunc = m_pub_funcs[index];
   4.108  	} else if (pFunc->IsInvalidated()) {
   4.109 @@ -1009,7 +1024,7 @@
   4.110  		GetPublicByIndex(index, &pub);
   4.111  		if (pub)
   4.112  		{
   4.113 -			pFunc->Set(pub->code_offs, this);
   4.114 +			pFunc->Set(pub->code_offs, this, pub->funcid);
   4.115  		} else {
   4.116  			pFunc = NULL;
   4.117  		}
     5.1 --- a/core/vm/sp_vm_function.cpp	Wed Aug 15 18:26:15 2007 +0000
     5.2 +++ b/core/vm/sp_vm_function.cpp	Wed Aug 15 20:18:15 2007 +0000
     5.3 @@ -37,7 +37,7 @@
     5.4  * FUNCTION CALLING *
     5.5  ********************/
     5.6  
     5.7 -void CFunction::Set(uint32_t code_addr, IPluginContext *plugin)
     5.8 +void CFunction::Set(uint32_t code_addr, IPluginContext *plugin, funcid_t id)
     5.9  {
    5.10  	m_codeaddr = code_addr;
    5.11  	m_pContext = plugin;
    5.12 @@ -45,6 +45,7 @@
    5.13  	m_errorstate = SP_ERROR_NONE;
    5.14  	m_Invalid = false;
    5.15  	m_pCtx = plugin ? plugin->GetContext() : NULL;
    5.16 +	m_FnId = id;
    5.17  }
    5.18  
    5.19  bool CFunction::IsRunnable()
    5.20 @@ -72,9 +73,9 @@
    5.21  	return m_pContext;
    5.22  }
    5.23  
    5.24 -CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin) : 
    5.25 +CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin, funcid_t id) : 
    5.26  	m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0), 
    5.27 -	m_errorstate(SP_ERROR_NONE)
    5.28 +	m_errorstate(SP_ERROR_NONE), m_FnId(id)
    5.29  {
    5.30  	m_Invalid = false;
    5.31  	if (plugin)
    5.32 @@ -313,3 +314,8 @@
    5.33  
    5.34  	return err;
    5.35  }
    5.36 +
    5.37 +funcid_t CFunction::GetFunctionID()
    5.38 +{
    5.39 +	return m_FnId;
    5.40 +}
     6.1 --- a/core/vm/sp_vm_function.h	Wed Aug 15 18:26:15 2007 +0000
     6.2 +++ b/core/vm/sp_vm_function.h	Wed Aug 15 20:18:15 2007 +0000
     6.3 @@ -55,7 +55,7 @@
     6.4  {
     6.5  	friend class SourcePawnEngine;
     6.6  public:
     6.7 -	CFunction(uint32_t code_addr, IPluginContext *pContext);
     6.8 +	CFunction(uint32_t code_addr, IPluginContext *pContext, funcid_t fnid);
     6.9  public:
    6.10  	virtual int PushCell(cell_t cell);
    6.11  	virtual int PushCellByRef(cell_t *cell, int flags);
    6.12 @@ -77,8 +77,9 @@
    6.13  		m_Invalid = true;
    6.14  	}
    6.15  	bool IsRunnable();
    6.16 +	funcid_t GetFunctionID();
    6.17  public:
    6.18 -	void Set(uint32_t code_addr, IPluginContext *plugin);
    6.19 +	void Set(uint32_t code_addr, IPluginContext *plugin, funcid_t fnid);
    6.20  private:
    6.21  	int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
    6.22  	inline int SetError(int err)
    6.23 @@ -96,6 +97,7 @@
    6.24  	int m_errorstate;
    6.25  	CFunction *m_pNext;
    6.26  	bool m_Invalid;
    6.27 +	funcid_t m_FnId;
    6.28  };
    6.29  
    6.30  #endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_