From 0b131d6864549b419e6aa5ae5180fc74704f0828 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Sun, 13 Jul 2014 13:56:47 +0200 Subject: [PATCH 1/2] Pause dependent plugins on SetFailState (bug 6120) When a plugin calls SetFailState it is paused and all natives it registered are unavailable. Other plugins, which depend on those natives keep running and error whenever they try to call those natives. This correctly sets the dependent plugins to an error state as if the plugin which called SetFailState was unloaded. --- core/logic/PluginSys.cpp | 31 +++++++++++++++++++------------ core/logic/smn_core.cpp | 8 ++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index c53d4fe3..a22544df 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -195,15 +195,20 @@ IPluginRuntime *CPlugin::GetRuntime() void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...) { - PluginStatus old_status = m_status; - m_status = status; - - if (old_status == Plugin_Running) + if (m_status == Plugin_Running) { /* Tell everyone we're now paused */ - g_PluginSys._SetPauseState(this, true); + SetPauseState(true); + /* If we won't recover from this error, drop everything and pause dependent plugins too! */ + if (status == Plugin_Failed) + { + DropEverything(); + } } + /* SetPauseState sets the status to Plugin_Paused, but we might want to see some other status set. */ + m_status = status; + va_list ap; va_start(ap, error_fmt); smcore.FormatArgs(m_errormsg, sizeof(m_errormsg), error_fmt, ap); @@ -531,7 +536,8 @@ bool CPlugin::SetPauseState(bool paused) if (paused && GetStatus() != Plugin_Running) { return false; - } else if (!paused && GetStatus() != Plugin_Paused) { + } + else if (!paused && GetStatus() != Plugin_Paused && GetStatus() != Plugin_Error) { return false; } @@ -539,6 +545,12 @@ bool CPlugin::SetPauseState(bool paused) { LibraryActions(LibraryAction_Removed); } + else + { + // Set to running again BEFORE trying to call OnPluginPauseChange ;) + m_status = Plugin_Running; + m_pRuntime->SetPauseState(false); + } IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange"); if (pFunction) @@ -552,9 +564,6 @@ bool CPlugin::SetPauseState(bool paused) { m_status = Plugin_Paused; m_pRuntime->SetPauseState(true); - } else { - m_status = Plugin_Running; - m_pRuntime->SetPauseState(false); } g_PluginSys._SetPauseState(this, paused); @@ -1496,11 +1505,9 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin) if (pPlugin->GetStatus() == Plugin_Error) { /* If we got here, all natives are okay again! */ - pPlugin->m_status = Plugin_Running; if (pPlugin->m_pRuntime->IsPaused()) { - pPlugin->m_pRuntime->SetPauseState(false); - _SetPauseState(pPlugin, false); + pPlugin->SetPauseState(false); } } } diff --git a/core/logic/smn_core.cpp b/core/logic/smn_core.cpp index 50eb0e5d..c595ebab 100644 --- a/core/logic/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -380,7 +380,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params) if (params[0] == 1) { - pPlugin->SetErrorState(Plugin_Error, "%s", str); + pPlugin->SetErrorState(Plugin_Failed, "%s", str); return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str); } @@ -391,12 +391,12 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params) g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { - pPlugin->SetErrorState(Plugin_Error, "%s", str); + pPlugin->SetErrorState(Plugin_Failed, "%s", str); return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str); } else { - pPlugin->SetErrorState(Plugin_Error, "%s", buffer); + pPlugin->SetErrorState(Plugin_Failed, "%s", buffer); return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer); } } @@ -774,4 +774,4 @@ REGISTER_NATIVES(coreNatives) {"LoadFromAddress", LoadFromAddress}, {"StoreToAddress", StoreToAddress}, {NULL, NULL}, -}; \ No newline at end of file +}; From 9b2e77711aedf663cb753a97f8a53bcd4aec5804 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Wed, 29 Oct 2014 17:13:43 +0100 Subject: [PATCH 2/2] Plugin_Failed == "An unrecoverable error" Change the meaning of Plugin_Failed status to indicate, that the plugin can't recover from the error. Make sure those previously loaded plugins are shown correctly in sm plugins info x. --- core/logic/PluginSys.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index a22544df..ae7935f1 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1147,7 +1147,7 @@ void CPluginManager::LoadAll_SecondPass() if (!RunSecondPass(pPlugin, error, sizeof(error))) { g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); - pPlugin->SetErrorState(Plugin_Failed, "%s", error); + pPlugin->SetErrorState(Plugin_BadLoad, "%s", error); } } } @@ -2224,7 +2224,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c const sm_plugininfo_t *info = pl->GetPublicInfo(); rootmenu->ConsolePrint(" Filename: %s", pl->GetFilename()); - if (pl->GetStatus() <= Plugin_Error) + if (pl->GetStatus() <= Plugin_Error || pl->GetStatus() == Plugin_Failed) { if (IS_STR_FILLED(info->name)) { @@ -2247,7 +2247,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c { rootmenu->ConsolePrint(" URL: %s", info->url); } - if (pl->GetStatus() == Plugin_Error) + if (pl->GetStatus() == Plugin_Error || pl->GetStatus() == Plugin_Failed) { rootmenu->ConsolePrint(" Error: %s", pl->m_errormsg); }