Compare commits

...

1 Commits

Author SHA1 Message Date
Poggu
7baf0a25e2 Prevent calling natives on non-main thread (#170)
Co-authored-by: Michael Wilson <roflmuffin@users.noreply.github.com>
Co-authored-by: Roflmuffin <shortguy014@gmail.com>
2023-12-04 18:26:36 +10:00
5 changed files with 34 additions and 1 deletions

View File

@@ -78,6 +78,7 @@ ChatManager chatManager;
ServerManager serverManager;
GetLegacyGameEventListener_t* GetLegacyGameEventListener = nullptr;
std::thread::id gameThreadId;
void Initialize()
{

View File

@@ -6,6 +6,8 @@
#undef protected
#undef private
#include <thread>
#include "ISmmAPI.h"
#include "eiface.h"
#include "iserver.h"
@@ -107,6 +109,7 @@ extern CGameConfig* gameConfig;
typedef IGameEventListener2 *GetLegacyGameEventListener_t(CPlayerSlot slot);
extern GetLegacyGameEventListener_t* GetLegacyGameEventListener;
extern std::thread::id gameThreadId;
void Initialize();
// Should only be called within the active game loop (i e map should be loaded

View File

@@ -41,6 +41,17 @@ DLL_EXPORT void InvokeNative(counterstrikesharp::fxNativeContext& context)
if (context.nativeIdentifier == 0)
return;
if (context.nativeIdentifier != counterstrikesharp::hash_string_const("QUEUE_TASK_FOR_NEXT_FRAME") &&
context.nativeIdentifier != counterstrikesharp::hash_string_const("QUEUE_TASK_FOR_NEXT_WORLD_UPDATE") &&
counterstrikesharp::globals::gameThreadId != std::this_thread::get_id())
{
counterstrikesharp::ScriptContextRaw scriptContext(context);
scriptContext.ThrowNativeError("Invoked on a non-main thread");
CSSHARP_CORE_CRITICAL("Native {:x} was invoked on a non-main thread", context.nativeIdentifier);
return;
}
counterstrikesharp::ScriptEngine::InvokeNative(context);
}
@@ -67,6 +78,7 @@ bool CounterStrikeSharpMMPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, s
{
PLUGIN_SAVEVARS();
globals::ismm = ismm;
globals::gameThreadId = std::this_thread::get_id();
Log::Init();
@@ -164,6 +176,8 @@ void CounterStrikeSharpMMPlugin::AllPluginsLoaded()
void CounterStrikeSharpMMPlugin::AddTaskForNextFrame(std::function<void()>&& task)
{
std::lock_guard<std::mutex> lock(m_nextTasksLock);
m_nextTasks.push_back(std::forward<decltype(task)>(task));
}
@@ -177,6 +191,8 @@ void CounterStrikeSharpMMPlugin::Hook_GameFrame(bool simulating, bool bFirstTick
*/
globals::timerSystem.OnGameFrame(simulating);
std::lock_guard<std::mutex> lock(m_nextTasksLock);
if (m_nextTasks.empty())
return;
@@ -225,4 +241,4 @@ const char* CounterStrikeSharpMMPlugin::GetURL()
{
return "https://github.com/roflmuffin/CounterStrikeSharp";
}
} // namespace counterstrikesharp
} // namespace counterstrikesharp

View File

@@ -61,6 +61,7 @@ public:
private:
std::vector<std::function<void()>> m_nextTasks;
std::mutex m_nextTasksLock;
};
static ScriptCallback *on_activate_callback;

View File

@@ -55,6 +55,18 @@ inline uint32_t hash_string(const char *string) {
return result;
}
template<size_t N>
constexpr uint32_t hash_string_const(char const (&string)[N])
{
unsigned long result = 5381;
for (size_t i = 0; i < N-1; i++) {
result = ((result << 5) + result) ^ string[i];
}
return result;
}
struct fxNativeContext {
int numArguments;
int numResults;