Skip to content

Commit ffef700

Browse files
committed
Fixed an infinite recursion when a server output callback is raising.
Replaced Windows' API in favour of cross-platform CThreadMutex. Removed some duplicate code.
1 parent 109ccc6 commit ffef700

File tree

3 files changed

+21
-30
lines changed

3 files changed

+21
-30
lines changed

src/core/modules/listeners/listeners_manager.cpp

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
//-----------------------------------------------------------------------------
3030
#include "listeners_manager.h"
3131
#include "sp_main.h"
32+
#include "utilities/sp_util.h"
3233

3334

3435
//-----------------------------------------------------------------------------
@@ -171,12 +172,7 @@ SpewRetval_t SP_SpewOutput( SpewType_t spewType, const tchar *pMsg )
171172
{
172173
static CServerOutputListenerManager *pManager = GetOnServerOutputListenerManager();
173174

174-
bool block = false;
175-
EnterCriticalSection(&pManager->m_pCriticalSection); {
176-
block = pManager->CallCallbacks((MessageSeverity)spewType, pMsg);
177-
} LeaveCriticalSection(&pManager->m_pCriticalSection);
178-
179-
if (!block && pManager->m_pOldSpewOutputFunc) {
175+
if (!pManager->CallCallbacks((MessageSeverity)spewType, pMsg) && pManager->m_pOldSpewOutputFunc) {
180176
return pManager->m_pOldSpewOutputFunc(spewType, pMsg);
181177
}
182178

@@ -190,12 +186,7 @@ class SPLoggingListener: public ILoggingListener
190186
{
191187
static CServerOutputListenerManager *pManager = GetOnServerOutputListenerManager();
192188

193-
bool block = false;
194-
EnterCriticalSection(&pManager->m_pCriticalSection); {
195-
block = pManager->CallCallbacks((MessageSeverity)pContext->m_Severity, pMessage);
196-
} LeaveCriticalSection(&pManager->m_pCriticalSection);
197-
198-
if (!block)
189+
if (!pManager->CallCallbacks((MessageSeverity)pContext->m_Severity, pMessage))
199190
{
200191
// Restore the old logging state before SP has been loaded
201192
LoggingSystem_PopLoggingState(false);
@@ -230,7 +221,6 @@ CServerOutputListenerManager::CServerOutputListenerManager()
230221
:m_pOldSpewOutputFunc(NULL)
231222
#endif
232223
{
233-
InitializeCriticalSection(&m_pCriticalSection);
234224
}
235225

236226

@@ -280,15 +270,18 @@ void CServerOutputListenerManager::Finalize()
280270
bool CServerOutputListenerManager::CallCallbacks(MessageSeverity severity, const tchar *pMsg)
281271
{
282272
bool block = false;
283-
FOR_EACH_VEC(m_vecCallables, i) {
284-
BEGIN_BOOST_PY()
285-
object return_value = m_vecCallables[i](severity, pMsg);
286-
287-
if (!return_value.is_none() && extract<OutputReturn>(return_value) == OUTPUT_BLOCK)
288-
block = true;
289-
290-
END_BOOST_PY_NORET()
291-
}
273+
m_Mutex.Lock(); {
274+
FOR_EACH_VEC(m_vecCallables, i) {
275+
try {
276+
object return_value = m_vecCallables[i](severity, pMsg);
277+
278+
if (!return_value.is_none() && extract<OutputReturn>(return_value) == OUTPUT_BLOCK)
279+
block = true;
280+
} catch (...) {
281+
PrintCurrentException(false);
282+
}
283+
}
284+
} m_Mutex.Unlock();
292285
return block;
293286
}
294287

src/core/modules/listeners/listeners_manager.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@
3838
#include "dbg.h"
3939
#include "tier0/threadtools.h"
4040

41-
#ifdef _WIN32
42-
#include <Windows.h>
43-
#endif
41+
4442

4543

4644
//-----------------------------------------------------------------------------
@@ -122,7 +120,7 @@ class CServerOutputListenerManager: public CListenerManager
122120
bool CallCallbacks(MessageSeverity severity, const tchar *pMsg);
123121

124122
public:
125-
CRITICAL_SECTION m_pCriticalSection;
123+
CThreadMutex m_Mutex;
126124

127125
#if defined(ENGINE_ORANGEBOX) || defined(ENGINE_BMS) || defined(ENGINE_GMOD)
128126
SpewOutputFunc_t m_pOldSpewOutputFunc;

src/core/utilities/sp_util.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ using namespace boost::python;
4646
//-----------------------------------------------------------------------------
4747
#define MAX_CHUNK 1024
4848

49-
inline void ChunkedMsg(const char* msg)
49+
inline void ChunkedMsg(const char* msg, bool bLogged = true)
5050
{
5151
char* pMsg = (char*) msg;
5252
int iLen = strlen(msg);
5353

5454
while(iLen > 0) {
55-
Msg("%s", pMsg);
55+
bLogged ? Msg("%s", pMsg) : printf("%s", pMsg);
5656
pMsg += MAX_CHUNK-1;
5757
iLen -= MAX_CHUNK-1;
5858
}
@@ -61,7 +61,7 @@ inline void ChunkedMsg(const char* msg)
6161
//-----------------------------------------------------------------------------
6262
// Prints and clear the current exception.
6363
//-----------------------------------------------------------------------------
64-
inline void PrintCurrentException()
64+
inline void PrintCurrentException(bool bLogged = true)
6565
{
6666
if (PyErr_Occurred())
6767
{
@@ -79,7 +79,7 @@ inline void PrintCurrentException()
7979
const char* pMsg = extract<const char *>(str("\n").join(format_exception(hType, hValue, hTraceback)));
8080

8181
// Send the message in chunks, because it can get quite big.
82-
ChunkedMsg(pMsg);
82+
ChunkedMsg(pMsg, bLogged);
8383

8484
PyErr_Clear();
8585
}

0 commit comments

Comments
 (0)