Don't use server commands to flush plugin unloads.
This commit is contained in:
parent
08cadcdda6
commit
c36f80b93d
@ -35,6 +35,9 @@ class IProviderCallbacks
|
|||||||
public:
|
public:
|
||||||
// Called when a log message is printed. Return true to supercede.
|
// Called when a log message is printed. Return true to supercede.
|
||||||
virtual bool OnLogPrint(const char *msg) = 0;
|
virtual bool OnLogPrint(const char *msg) = 0;
|
||||||
|
|
||||||
|
// Called each frame tick.
|
||||||
|
virtual void OnThink(bool simulating) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SourceMod
|
} // namespace SourceMod
|
||||||
|
@ -80,6 +80,7 @@ binary.sources += [
|
|||||||
'LibrarySys.cpp',
|
'LibrarySys.cpp',
|
||||||
'RootConsoleMenu.cpp',
|
'RootConsoleMenu.cpp',
|
||||||
'CDataPack.cpp',
|
'CDataPack.cpp',
|
||||||
|
'frame_tasks.cpp',
|
||||||
]
|
]
|
||||||
if builder.target_platform == 'windows':
|
if builder.target_platform == 'windows':
|
||||||
binary.sources += ['thread/WinThreads.cpp']
|
binary.sources += ['thread/WinThreads.cpp']
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include "Translator.h"
|
#include "Translator.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "frame_tasks.h"
|
||||||
#include <am-string.h>
|
#include <am-string.h>
|
||||||
#include <bridge/include/IVEngineServerBridge.h>
|
#include <bridge/include/IVEngineServerBridge.h>
|
||||||
#include <bridge/include/CoreProvider.h>
|
#include <bridge/include/CoreProvider.h>
|
||||||
@ -54,6 +55,7 @@ IdentityType_t g_PluginIdent = 0;
|
|||||||
CPlugin::CPlugin(const char *file)
|
CPlugin::CPlugin(const char *file)
|
||||||
: m_serial(0),
|
: m_serial(0),
|
||||||
m_status(Plugin_Uncompiled),
|
m_status(Plugin_Uncompiled),
|
||||||
|
m_WaitingToUnload(false),
|
||||||
m_SilentFailure(false),
|
m_SilentFailure(false),
|
||||||
m_FakeNativesMissing(false),
|
m_FakeNativesMissing(false),
|
||||||
m_LibraryMissing(false),
|
m_LibraryMissing(false),
|
||||||
@ -1422,7 +1424,13 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
|
|||||||
|
|
||||||
bool CPluginManager::UnloadPlugin(IPlugin *plugin)
|
bool CPluginManager::UnloadPlugin(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
return ScheduleUnload((CPlugin *)plugin);
|
CPlugin *pPlugin = (CPlugin *)plugin;
|
||||||
|
|
||||||
|
// If we're already in the unload queue, just wait.
|
||||||
|
if (pPlugin->WaitingToUnload())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ScheduleUnload(pPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPluginManager::ScheduleUnload(CPlugin *pPlugin)
|
bool CPluginManager::ScheduleUnload(CPlugin *pPlugin)
|
||||||
@ -1431,11 +1439,12 @@ bool CPluginManager::ScheduleUnload(CPlugin *pPlugin)
|
|||||||
assert(m_plugins.find(pPlugin) != m_plugins.end());
|
assert(m_plugins.find(pPlugin) != m_plugins.end());
|
||||||
|
|
||||||
IPluginContext *pContext = pPlugin->GetBaseContext();
|
IPluginContext *pContext = pPlugin->GetBaseContext();
|
||||||
if (pContext && pContext->IsInExec())
|
if (pContext && pContext->IsInExec()) {
|
||||||
{
|
ke::Lambda<void()> callback = [this, pPlugin]() {
|
||||||
char buffer[255];
|
this->ScheduleUnload(pPlugin);
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "sm plugins unload %s\n", pPlugin->GetFilename());
|
};
|
||||||
engine->ServerCommand(buffer);
|
pPlugin->SetWaitingToUnload();
|
||||||
|
ScheduleTaskForNextFrame(ke::Move(callback));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,29 +222,29 @@ public:
|
|||||||
*/
|
*/
|
||||||
IPhraseCollection *GetPhrases();
|
IPhraseCollection *GetPhrases();
|
||||||
public:
|
public:
|
||||||
/**
|
// Returns the modification time during last plugin load.
|
||||||
* Returns the modification time during last plugin load.
|
|
||||||
*/
|
|
||||||
time_t GetTimeStamp();
|
time_t GetTimeStamp();
|
||||||
|
|
||||||
/**
|
// Returns the current modification time of the plugin file.
|
||||||
* Returns the current modification time of the plugin file.
|
|
||||||
*/
|
|
||||||
time_t GetFileTimeStamp();
|
time_t GetFileTimeStamp();
|
||||||
|
|
||||||
/**
|
// Returns true if the plugin was running, but is now invalid.
|
||||||
* Returns true if the plugin was running, but is now invalid.
|
|
||||||
*/
|
|
||||||
bool WasRunning();
|
bool WasRunning();
|
||||||
|
|
||||||
|
bool WaitingToUnload() const {
|
||||||
|
return m_WaitingToUnload;
|
||||||
|
}
|
||||||
|
void SetWaitingToUnload() {
|
||||||
|
m_WaitingToUnload = true;
|
||||||
|
}
|
||||||
|
|
||||||
Handle_t GetMyHandle();
|
Handle_t GetMyHandle();
|
||||||
|
|
||||||
bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
|
bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
|
||||||
void AddConfig(bool autoCreate, const char *cfg, const char *folder);
|
void AddConfig(bool autoCreate, const char *cfg, const char *folder);
|
||||||
size_t GetConfigCount();
|
size_t GetConfigCount();
|
||||||
AutoConfig *GetConfig(size_t i);
|
AutoConfig *GetConfig(size_t i);
|
||||||
inline void AddLibrary(const char *name)
|
inline void AddLibrary(const char *name) {
|
||||||
{
|
|
||||||
m_Libraries.push_back(name);
|
m_Libraries.push_back(name);
|
||||||
}
|
}
|
||||||
void LibraryActions(LibraryAction action);
|
void LibraryActions(LibraryAction action);
|
||||||
@ -260,6 +260,7 @@ private:
|
|||||||
unsigned int m_serial;
|
unsigned int m_serial;
|
||||||
|
|
||||||
PluginStatus m_status;
|
PluginStatus m_status;
|
||||||
|
bool m_WaitingToUnload;
|
||||||
|
|
||||||
// Statuses that are set during failure.
|
// Statuses that are set during failure.
|
||||||
bool m_SilentFailure;
|
bool m_SilentFailure;
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "AdminCache.h"
|
#include "AdminCache.h"
|
||||||
#include "ProfileTools.h"
|
#include "ProfileTools.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "frame_tasks.h"
|
||||||
#include "sprintf.h"
|
#include "sprintf.h"
|
||||||
#include "LibrarySys.h"
|
#include "LibrarySys.h"
|
||||||
#include "RootConsoleMenu.h"
|
#include "RootConsoleMenu.h"
|
||||||
@ -137,6 +138,9 @@ public:
|
|||||||
bool OnLogPrint(const char *msg) override {
|
bool OnLogPrint(const char *msg) override {
|
||||||
return ::OnLogPrint(msg);
|
return ::OnLogPrint(msg);
|
||||||
}
|
}
|
||||||
|
void OnThink(bool simulating) override {
|
||||||
|
RunScheduledFrameTasks(simulating);
|
||||||
|
}
|
||||||
} sProviderCallbackListener;
|
} sProviderCallbackListener;
|
||||||
|
|
||||||
static sm_logic_t logic =
|
static sm_logic_t logic =
|
||||||
|
55
core/logic/frame_tasks.cpp
Normal file
55
core/logic/frame_tasks.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#include "frame_tasks.h"
|
||||||
|
#include <am-vector.h>
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
ke::Vector<ke::Lambda<void()>> sNextTasks;
|
||||||
|
ke::Vector<ke::Lambda<void()>> sWorkTasks;
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceMod::ScheduleTaskForNextFrame(ke::Lambda<void()>&& task)
|
||||||
|
{
|
||||||
|
sNextTasks.append(ke::Forward<decltype(task)>(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceMod::RunScheduledFrameTasks(bool simulating)
|
||||||
|
{
|
||||||
|
if (sNextTasks.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Swap.
|
||||||
|
ke::Vector<ke::Lambda<void()>> temp(ke::Move(sNextTasks));
|
||||||
|
sNextTasks = ke::Move(sWorkTasks);
|
||||||
|
sWorkTasks = ke::Move(temp);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sWorkTasks.length(); i++)
|
||||||
|
sWorkTasks[i]();
|
||||||
|
sWorkTasks.clear();
|
||||||
|
}
|
40
core/logic/frame_tasks.h
Normal file
40
core/logic/frame_tasks.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _include_sourcemod_logic_frame_tasks_h_
|
||||||
|
#define _include_sourcemod_logic_frame_tasks_h_
|
||||||
|
|
||||||
|
#include <am-function.h>
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
void ScheduleTaskForNextFrame(ke::Lambda<void()>&& task);
|
||||||
|
|
||||||
|
void RunScheduledFrameTasks(bool simulating);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _include_sourcemod_logic_frame_tasks_h_
|
@ -46,11 +46,13 @@
|
|||||||
#include <amtl/os/am-path.h>
|
#include <amtl/os/am-path.h>
|
||||||
#include <bridge/include/IExtensionBridge.h>
|
#include <bridge/include/IExtensionBridge.h>
|
||||||
#include <bridge/include/IScriptManager.h>
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
#include <bridge/include/IProviderCallbacks.h>
|
||||||
#include <bridge/include/ILogger.h>
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
||||||
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
||||||
SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
|
SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
|
||||||
|
SH_DECL_HOOK1_void(IServerGameDLL, Think, SH_NOATTRIB, false, bool);
|
||||||
SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
|
SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
|
||||||
|
|
||||||
SourceModBase g_SourceMod;
|
SourceModBase g_SourceMod;
|
||||||
@ -322,6 +324,8 @@ void SourceModBase::StartSourceMod(bool late)
|
|||||||
{
|
{
|
||||||
g_pSourcePawn2->InstallWatchdogTimer(atoi(timeout) * 1000);
|
g_pSourcePawn2->InstallWatchdogTimer(atoi(timeout) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SH_ADD_HOOK(IServerGameDLL, Think, gamedll, SH_MEMBER(logicore.callbacks, &IProviderCallbacks::OnThink), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool g_LevelEndBarrier = false;
|
static bool g_LevelEndBarrier = false;
|
||||||
@ -539,6 +543,7 @@ void SourceModBase::ShutdownServices()
|
|||||||
|
|
||||||
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
|
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
|
||||||
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
|
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
|
||||||
|
SH_REMOVE_HOOK(IServerGameDLL, Think, gamedll, SH_MEMBER(logicore.callbacks, &IProviderCallbacks::OnThink), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
||||||
|
Loading…
Reference in New Issue
Block a user