Catch exceptions from TraceRay filters/enumerators (#1557)

When a custom TraceRay filter / EnumerateEntities enumerator callback
throws an exception we currently continue execution and then return
execution to the calling code as if there were no problems. This
currently causes a heap tracking issue in SourcePawn, but even ignoring
that it is likely the wrong behaviour and differs from our other
synchronous callbacks.

This change causes the exception to be caught, immediately terminates
the trace / enumeration, and propagates the exception state back to the
calling plugin correctly. The implementation here is based on how
SortCustom1D handles exceptions.
This commit is contained in:
Asher Baker 2021-08-02 11:57:36 +01:00 committed by GitHub
parent e82f88dfa9
commit 3c79701208
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -56,20 +56,26 @@ class CSMTraceFilter : public CTraceFilter
public:
bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
{
if (m_pEh->HasException()) {
return true;
}
cell_t res = 1;
m_pFunc->PushCell(gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(pEntity)));
m_pFunc->PushCell(contentsMask);
m_pFunc->PushCell(m_Data);
m_pFunc->Execute(&res);
m_pFunc->Invoke(&res);
return (res) ? true : false;
}
void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
void SetFunctionPtr(ExceptionHandler *pEh, IPluginFunction *pFunc, cell_t data)
{
m_pEh = pEh;
m_pFunc = pFunc;
m_Data = data;
}
private:
ExceptionHandler *m_pEh;
IPluginFunction *m_pFunc;
cell_t m_Data;
};
@ -79,19 +85,25 @@ class CSMTraceEnumerator : public IPartitionEnumerator
public:
IterationRetval_t EnumElement(IHandleEntity *pEntity) override
{
if (m_pEh->HasException()) {
return ITERATION_STOP;
}
cell_t res = 1;
m_pFunc->PushCell(gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity*>(pEntity)));
m_pFunc->PushCell(m_Data);
m_pFunc->Execute(&res);
m_pFunc->Invoke(&res);
return (res) ? ITERATION_CONTINUE : ITERATION_STOP;
}
void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
void SetFunctionPtr(ExceptionHandler *pEh, IPluginFunction *pFunc, cell_t data)
{
m_pEh = pEh;
m_pFunc = pFunc;
m_Data = data;
}
private:
ExceptionHandler *m_pEh;
IPluginFunction *m_pFunc;
cell_t m_Data;
};
@ -196,7 +208,8 @@ static cell_t smn_TREnumerateEntities(IPluginContext *pContext, const cell_t *pa
data = params[6];
}
g_SMTraceEnumerator.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceEnumerator.SetFunctionPtr(&eh, pFunc, data);
cell_t *startaddr, *endaddr;
pContext->LocalToPhysAddr(params[1], &startaddr);
@ -245,7 +258,8 @@ static cell_t smn_TREnumerateEntitiesHull(IPluginContext *pContext, const cell_t
data = params[7];
}
g_SMTraceEnumerator.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceEnumerator.SetFunctionPtr(&eh, pFunc, data);
cell_t *startaddr, *endaddr, *mins, *maxs;
pContext->LocalToPhysAddr(params[1], &startaddr);
@ -280,7 +294,8 @@ static cell_t smn_TREnumerateEntitiesSphere(IPluginContext *pContext, const cell
data = params[5];
}
g_SMTraceEnumerator.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceEnumerator.SetFunctionPtr(&eh, pFunc, data);
cell_t *startaddr;
pContext->LocalToPhysAddr(params[1], &startaddr);
@ -309,7 +324,8 @@ static cell_t smn_TREnumerateEntitiesBox(IPluginContext *pContext, const cell_t
data = params[5];
}
g_SMTraceEnumerator.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceEnumerator.SetFunctionPtr(&eh, pFunc, data);
cell_t *minsaddr, *maxsaddr;
pContext->LocalToPhysAddr(params[1], &minsaddr);
@ -338,7 +354,8 @@ static cell_t smn_TREnumerateEntitiesPoint(IPluginContext *pContext, const cell_
data = params[4];
}
g_SMTraceEnumerator.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceEnumerator.SetFunctionPtr(&eh, pFunc, data);
cell_t *startaddr;
pContext->LocalToPhysAddr(params[1], &startaddr);
@ -457,7 +474,9 @@ static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *param
data = 0;
}
g_SMTraceFilter.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceFilter.SetFunctionPtr(&eh, pFunc, data);
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
@ -503,7 +522,9 @@ static cell_t smn_TRTraceHullFilter(IPluginContext *pContext, const cell_t *para
data = params[7];
g_SMTraceFilter.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
g_SMTraceFilter.SetFunctionPtr(&eh, pFunc, data);
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
pContext->LocalToPhysAddr(params[3], &mins);
@ -751,7 +772,9 @@ static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *par
data = 0;
}
smfilter.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
smfilter.SetFunctionPtr(&eh, pFunc, data);
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
switch (params[4])
@ -812,7 +835,9 @@ static cell_t smn_TRTraceHullFilterEx(IPluginContext *pContext, const cell_t *pa
data = params[7];
smfilter.SetFunctionPtr(pFunc, data);
DetectExceptions eh(pContext);
smfilter.SetFunctionPtr(&eh, pFunc, data);
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
vmins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
vmaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));