Reworked code to support error handling, LogError() is separate from DisplayTrace() implementation
This commit is contained in:
parent
4738c92b8e
commit
f8aac5e88d
|
@ -38,10 +38,11 @@
|
||||||
|
|
||||||
extern const char *no_function;
|
extern const char *no_function;
|
||||||
|
|
||||||
CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug) {
|
CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug)
|
||||||
|
{
|
||||||
CPlugin** a = &head;
|
CPlugin** a = &head;
|
||||||
while( *a ) a = &(*a)->next;
|
while( *a ) a = &(*a)->next;
|
||||||
*a = new CPlugin( pCounter++ ,path,name,error, debug);
|
*a = new CPlugin(pCounter++, path, name, error, debug);
|
||||||
return (*a);
|
return (*a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -339,6 +339,7 @@ enum {
|
||||||
#define UD_FINDPLUGIN 3
|
#define UD_FINDPLUGIN 3
|
||||||
#define UD_DEBUGGER 2
|
#define UD_DEBUGGER 2
|
||||||
#define UD_OPCODELIST 1
|
#define UD_OPCODELIST 1
|
||||||
|
#define UD_HANDLER 0
|
||||||
|
|
||||||
/* for native functions that use floating point parameters, the following
|
/* for native functions that use floating point parameters, the following
|
||||||
* two macros are convenient for casting a "cell" into a "float" type _without_
|
* two macros are convenient for casting a "cell" into a "float" type _without_
|
||||||
|
|
|
@ -149,6 +149,7 @@ extern CList<ForceObject> g_forcemodels;
|
||||||
extern CList<ForceObject> g_forcesounds;
|
extern CList<ForceObject> g_forcesounds;
|
||||||
extern CList<ForceObject> g_forcegeneric;
|
extern CList<ForceObject> g_forcegeneric;
|
||||||
extern CList<CModule,const char *> g_modules;
|
extern CList<CModule,const char *> g_modules;
|
||||||
|
extern CList<CScript,AMX*> g_loadedscripts;
|
||||||
extern CList<CPlayer*> g_auth;
|
extern CList<CPlayer*> g_auth;
|
||||||
extern EventsMngr g_events;
|
extern EventsMngr g_events;
|
||||||
extern Grenades g_grenades;
|
extern Grenades g_grenades;
|
||||||
|
|
|
@ -778,7 +778,100 @@ void Debugger::Clear()
|
||||||
m_pCalls.clear();
|
m_pCalls.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Debugger::DisplayTrace(const char *message)
|
||||||
|
{
|
||||||
|
if (message != NULL)
|
||||||
|
AMXXLOG_Log("%s", message);
|
||||||
|
|
||||||
|
char buffer[512];
|
||||||
|
FormatError(buffer, sizeof(buffer)-1);
|
||||||
|
|
||||||
|
const char *filename = _GetFilename();
|
||||||
|
|
||||||
|
AMXXLOG_Log("[AMXX] Displaying debug trace (plugin \"%s\")", filename);
|
||||||
|
AMXXLOG_Log("[AMXX] %s", buffer);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
long lLine;
|
||||||
|
const char *file, *function;
|
||||||
|
trace_info_t *pTrace = GetTraceStart();
|
||||||
|
while (pTrace)
|
||||||
|
{
|
||||||
|
GetTraceInfo(pTrace, lLine, function, file);
|
||||||
|
AMXXLOG_Log(
|
||||||
|
"[AMXX] [%d] %s::%s (line %d)",
|
||||||
|
count,
|
||||||
|
file,
|
||||||
|
function,
|
||||||
|
(int)(lLine + 1)
|
||||||
|
);
|
||||||
|
count++;
|
||||||
|
pTrace = GetNextTrace(pTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Debugger::_GetFilename()
|
||||||
|
{
|
||||||
|
if (m_FileName.size() < 1)
|
||||||
|
{
|
||||||
|
const char *filename = "";
|
||||||
|
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
|
||||||
|
if (pl)
|
||||||
|
{
|
||||||
|
filename = pl->getName();
|
||||||
|
} else {
|
||||||
|
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(m_pAmx);
|
||||||
|
if (a)
|
||||||
|
filename = (*a).getName();
|
||||||
|
}
|
||||||
|
m_FileName.assign(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_FileName.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
Debugger::~Debugger()
|
Debugger::~Debugger()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Handler::SetErrorHandler(const char *function)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = amx_FindPublic(m_pAmx, function, &m_iErrFunc);
|
||||||
|
|
||||||
|
if (error != AMX_ERR_NONE)
|
||||||
|
m_iErrFunc = -1;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler::SetModuleFilter(const char *function)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = amx_FindPublic(m_pAmx, function, &m_iModFunc);
|
||||||
|
|
||||||
|
if (error != AMX_ERR_NONE)
|
||||||
|
m_iModFunc = -1;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler::SetNativeFilter(const char *function)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = amx_FindPublic(m_pAmx, function, &m_iNatFunc);
|
||||||
|
|
||||||
|
if (error != AMX_ERR_NONE)
|
||||||
|
m_iNatFunc = -1;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler::HandleError(const char *msg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -116,6 +116,10 @@ public:
|
||||||
|
|
||||||
//Destroy internal states for shutdown
|
//Destroy internal states for shutdown
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
void DisplayTrace(const char *message);
|
||||||
|
|
||||||
|
AMX *GetAMX() const { return m_pAmx; }
|
||||||
public:
|
public:
|
||||||
//generic static opcode breaker
|
//generic static opcode breaker
|
||||||
static int AMXAPI DebugHook(AMX *amx);
|
static int AMXAPI DebugHook(AMX *amx);
|
||||||
|
@ -123,14 +127,42 @@ private:
|
||||||
void _CacheAmxOpcodeList();
|
void _CacheAmxOpcodeList();
|
||||||
int _GetOpcodeFromCip(cell cip, cell *&addr);
|
int _GetOpcodeFromCip(cell cip, cell *&addr);
|
||||||
cell _CipAsVa(cell cip);
|
cell _CipAsVa(cell cip);
|
||||||
|
const char *_GetFilename();
|
||||||
public:
|
public:
|
||||||
AMX *m_pAmx;
|
AMX *m_pAmx;
|
||||||
AMX_DBG *m_pAmxDbg;
|
AMX_DBG *m_pAmxDbg;
|
||||||
int m_Top;
|
int m_Top;
|
||||||
cell *m_pOpcodeList;
|
cell *m_pOpcodeList;
|
||||||
|
String m_FileName;
|
||||||
CVector<Tracer *> m_pCalls;
|
CVector<Tracer *> m_pCalls;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Debugger::Tracer::trace_info trace_info_t;
|
typedef Debugger::Tracer::trace_info trace_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error handler for plugins
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Handler(AMX *pAmx) : m_pAmx(pAmx),
|
||||||
|
m_iErrFunc(-1), m_iModFunc(-1), m_iNatFunc(-1)
|
||||||
|
{ };
|
||||||
|
~Handler() { };
|
||||||
|
public:
|
||||||
|
int SetErrorHandler(const char *function);
|
||||||
|
int SetNativeFilter(const char *function);
|
||||||
|
int SetModuleFilter(const char *function);
|
||||||
|
public:
|
||||||
|
int HandleError(const char *msg);
|
||||||
|
int HandleNative(const char *native);
|
||||||
|
int HandleModule(const char *module);
|
||||||
|
public:
|
||||||
|
AMX *m_pAmx;
|
||||||
|
int m_iErrFunc;
|
||||||
|
int m_iModFunc;
|
||||||
|
int m_iNatFunc;
|
||||||
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_DEBUGGER_H_
|
#endif //_INCLUDE_DEBUGGER_H_
|
||||||
|
|
|
@ -1289,6 +1289,29 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
|
||||||
Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
|
Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
|
||||||
|
|
||||||
amx->error = err;
|
amx->error = err;
|
||||||
|
|
||||||
|
char msg_buffer[2048];
|
||||||
|
|
||||||
|
msg_buffer[0] = '\0';
|
||||||
|
if (fmt != NULL)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
_vsnprintf(msg_buffer, sizeof(msg_buffer)-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
//give the plugin first chance to handle any sort of error
|
||||||
|
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
|
||||||
|
if (pHandler)
|
||||||
|
{
|
||||||
|
//give the user a first-chance at blocking the error from displaying
|
||||||
|
if (pHandler->HandleError(msg_buffer) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pDebugger)
|
||||||
|
{
|
||||||
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
|
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
|
||||||
|
|
||||||
const char *filename = "";
|
const char *filename = "";
|
||||||
|
@ -1300,53 +1323,17 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
|
||||||
if (a)
|
if (a)
|
||||||
filename = (*a).getName();
|
filename = (*a).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
static char msg_buffer[4096];
|
|
||||||
if (fmt != NULL)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
_vsnprintf(msg_buffer, sizeof(msg_buffer)-1, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fmt != NULL)
|
if (fmt != NULL)
|
||||||
AMXXLOG_Log("%s", msg_buffer);
|
AMXXLOG_Log("%s", msg_buffer);
|
||||||
|
|
||||||
if (!pDebugger)
|
|
||||||
{
|
|
||||||
//give the module's error first. makes the report look nicer.
|
//give the module's error first. makes the report look nicer.
|
||||||
AMXXLOG_Log("[AMXX] Run time error %d (plugin \"%s\") - debug not enabled!", err, filename);
|
AMXXLOG_Log("[AMXX] Run time error %d (plugin \"%s\") - debug not enabled!", err, filename);
|
||||||
AMXXLOG_Log("[AMXX] To enable debug mode, add \"debug\" after the plugin name in plugins.ini (without quotes).");
|
AMXXLOG_Log("[AMXX] To enable debug mode, add \"debug\" after the plugin name in plugins.ini (without quotes).");
|
||||||
//destroy original error code so the original is not displayed again
|
//destroy original error code so the original is not displayed again
|
||||||
amx->error = -1;
|
amx->error = -1;
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
pDebugger->SetTracedError(err);
|
pDebugger->SetTracedError(err);
|
||||||
|
//we can display error now
|
||||||
char buffer[512];
|
pDebugger->DisplayTrace(fmt ? msg_buffer : NULL);
|
||||||
pDebugger->FormatError(buffer, sizeof(buffer)-1);
|
|
||||||
|
|
||||||
AMXXLOG_Log("[AMXX] Displaying debug trace (plugin \"%s\")", filename);
|
|
||||||
AMXXLOG_Log("[AMXX] %s", buffer);
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
long lLine;
|
|
||||||
const char *file, *function;
|
|
||||||
trace_info_t *pTrace = pDebugger->GetTraceStart();
|
|
||||||
while (pTrace)
|
|
||||||
{
|
|
||||||
pDebugger->GetTraceInfo(pTrace, lLine, function, file);
|
|
||||||
AMXXLOG_Log(
|
|
||||||
"[AMXX] [%d] %s::%s (line %d)",
|
|
||||||
count,
|
|
||||||
file,
|
|
||||||
function,
|
|
||||||
(int)(lLine + 1)
|
|
||||||
);
|
|
||||||
count++;
|
|
||||||
pTrace = pDebugger->GetNextTrace(pTrace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user