[FarGroup/FarManager] master: Clarify plugin unloading logic in corner cases (fa46bd860)

0 views
Skip to first unread message

farg...@farmanager.com

unread,
Mar 14, 2026, 2:45:54 PM (13 days ago) Mar 14
to farco...@googlegroups.com
Repository : https://github.com/FarGroup/FarManager
On branch : master
Link : https://github.com/FarGroup/FarManager/commit/fa46bd860548c0df53f45bad3d01b73f4932f870

>---------------------------------------------------------------

commit fa46bd860548c0df53f45bad3d01b73f4932f870
Author: Alex Alabuzhev <alab...@gmail.com>
Date: Sat Mar 14 18:40:42 2026 +0000

Clarify plugin unloading logic in corner cases


>---------------------------------------------------------------

fa46bd860548c0df53f45bad3d01b73f4932f870
far/changelog | 5 +++++
far/plclass.cpp | 57 ++++++++++++++++++++++++++-------------------------------
far/plclass.hpp | 6 +++---
far/plugins.cpp | 21 ++++++++++++++-------
far/vbuild.m4 | 2 +-
5 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/far/changelog b/far/changelog
index 530d5d0de..761e8fa1d 100644
--- a/far/changelog
+++ b/far/changelog
@@ -1,3 +1,8 @@
+--------------------------------------------------------------------------------
+drkns 2026-03-14 18:40:14+00:00 - build 6661
+
+1. Clarify plugin unloading logic in corner cases.
+
--------------------------------------------------------------------------------
drkns 2026-03-13 00:23:35+00:00 - build 6660

diff --git a/far/plclass.cpp b/far/plclass.cpp
index ea57d151b..7181906ef 100644
--- a/far/plclass.cpp
+++ b/far/plclass.cpp
@@ -58,7 +58,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Platform:
#include "platform.env.hpp"
#include "platform.fs.hpp"
-#include "platform.process.hpp"

// Common:
#include "common/enum_tokens.hpp"
@@ -594,7 +593,7 @@ bool Plugin::LoadData()

bool ok = false;

- if (Info.Guid != FarUuid)
+ if (CheckMinFarVersion() && Info.Guid != FarUuid)
{
if (m_Uuid != FarUuid && m_Uuid != Info.Guid)
{
@@ -614,7 +613,7 @@ bool Plugin::LoadData()
return true;
}
}
- Unload(false);
+ Unload();
//чтоб не пытаться загрузить опять а то ошибка будет постоянно показываться.
WorkFlags.Set(PIWF_DONTLOADAGAIN);
return false;
@@ -622,32 +621,27 @@ bool Plugin::LoadData()

bool Plugin::Load()
{
+ if (WorkFlags.Check(PIWF_LOADED))
+ return true;
+
if (WorkFlags.Check(PIWF_DONTLOADAGAIN))
return false;

if (!WorkFlags.Check(PIWF_DATALOADED)&&!LoadData())
return false;

- if (WorkFlags.Check(PIWF_LOADED))
- return true;
-
+ // Must be set before calling SetStartupInfo: it can cause recursive loading
WorkFlags.Set(PIWF_LOADED);

- bool Inited = false;
+ PluginStartupInfo info;
+ FarStandardFunctions fsf;
+ CreatePluginStartupInfo(this, &info, &fsf);

- if (CheckMinFarVersion())
- {
- PluginStartupInfo info;
- FarStandardFunctions fsf;
- CreatePluginStartupInfo(this, &info, &fsf);
- Inited = SetStartupInfo(&info);
- }
-
- if (!Inited)
+ if (!SetStartupInfo(&info))
{
if (!bPendingRemove)
{
- Unload(false);
+ Unload();
}

//чтоб не пытаться загрузить опять а то ошибка будет постоянно показываться.
@@ -714,26 +708,26 @@ bool Plugin::LoadFromCache(const os::fs::find_data &FindData)
return true;
}

-bool Plugin::Unload(bool bExitFAR)
+bool Plugin::Unload()
{
- if (!WorkFlags.Check(PIWF_LOADED))
- return true;
-
- if (bExitFAR)
- NotifyExit();
+ NotifyExit();

bool Result = true;

if (!WorkFlags.Check(PIWF_CACHED))
{
Result = m_Factory->Destroy(m_Instance);
- LOGDEBUG(L"Unloaded {}"sv, ModuleName());
+
ClearExports();
+ WorkFlags.Clear(PIWF_DATALOADED);
+
+ if (Result)
+ LOGDEBUG(L"Unloaded {}"sv, ModuleName());
+ else
+ LOGWARNING(L"Failed to unload {}"sv, ModuleName());
}

m_Instance = nullptr;
- WorkFlags.Clear(PIWF_LOADED);
- WorkFlags.Clear(PIWF_DATALOADED);
bPendingRemove = true;

return Result;
@@ -741,11 +735,12 @@ bool Plugin::Unload(bool bExitFAR)

void Plugin::NotifyExit()
{
- if (WorkFlags.Check(PIWF_LOADED))
- {
- ExitInfo Info{sizeof(Info)};
- ExitFAR(&Info);
- }
+ if (!WorkFlags.Check(PIWF_LOADED))
+ return;
+
+ ExitInfo Info{sizeof(Info)};
+ ExitFAR(&Info);
+ WorkFlags.Clear(PIWF_LOADED);
}

void Plugin::ClearExports()
diff --git a/far/plclass.hpp b/far/plclass.hpp
index 37c1904bc..1ac5cfb05 100644
--- a/far/plclass.hpp
+++ b/far/plclass.hpp
@@ -104,11 +104,11 @@ enum export_index

enum PLUGINWORKFLAGS
{
- PIWF_LOADED = 0_bit, // DLL загружена
+ PIWF_LOADED = 0_bit, // Fully and properly loaded. SetStartupInfoW was called, unloading will trigger ExitFARW
PIWF_CACHED = 1_bit, // кешируется
PIWF_PRELOADED = 2_bit, //
PIWF_DONTLOADAGAIN = 3_bit, // не загружать плагин снова, ставится в результате проверки требуемой версии фара
- PIWF_DATALOADED = 4_bit, // LoadData успешно выполнилась
+ PIWF_DATALOADED = 4_bit, // Partially loaded, GetGlobalInfoW was called, but SetStartupInfoW wasn't. Unloading will not trigger ExitFARW
};

class i_plugin_module
@@ -295,7 +295,7 @@ public:

bool Load();
void NotifyExit();
- bool Unload(bool bExitFAR);
+ bool Unload();
bool LoadData();
bool LoadFromCache(const os::fs::find_data &FindData);
bool SaveToCache();
diff --git a/far/plugins.cpp b/far/plugins.cpp
index 4341f8744..301e9430c 100644
--- a/far/plugins.cpp
+++ b/far/plugins.cpp
@@ -143,7 +143,10 @@ PluginManager::PluginManager():
void PluginManager::NotifyExitLuaMacro() const
{
if (const auto LuaMacro = m_Plugins.find(Global->Opt->KnownIDs.Luamacro.Id); LuaMacro != m_Plugins.cend())
+ {
LuaMacro->second->NotifyExit();
+ LuaMacro->second->WorkFlags.Set(PIWF_DONTLOADAGAIN);
+ }
}

void PluginManager::UnloadPlugins()
@@ -158,18 +161,22 @@ void PluginManager::UnloadPlugins()
}
else
{
- i->Unload(true);
+ i->Unload();
+ // Just to make sure other plugins' ExitFAR won't bring it back from the dead somehow
+ i->WorkFlags.Set(PIWF_DONTLOADAGAIN);
}
}

if (Luamacro)
{
- Luamacro->Unload(false);
+ Luamacro->Unload();
}

// some plugins might still have dialogs (if DialogFree wasn't called)
// better to delete them explicitly while manager is still alive
m_Plugins.clear();
+ SortedPlugins.clear();
+ UnloadedPlugins.clear();
}

Plugin* PluginManager::AddPlugin(std::unique_ptr<Plugin>&& pPlugin)
@@ -178,7 +185,7 @@ Plugin* PluginManager::AddPlugin(std::unique_ptr<Plugin>&& pPlugin)
if (!IsEmplaced)
{
LOGWARNING(L"Plugin \"{}\" is already loaded from {}, ignoring {}"sv, Iterator->second->Title(), Iterator->second->ModuleName(), pPlugin->ModuleName());
- pPlugin->Unload(true);
+ pPlugin->Unload();
return nullptr;
}
Iterator->second = std::move(pPlugin);
@@ -261,7 +268,7 @@ Plugin* PluginManager::LoadPlugin(const string& FileName, const os::fs::find_dat

if (bDataLoaded && !PluginPtr->Load())
{
- PluginPtr->Unload(true);
+ PluginPtr->Unload();
RemovePlugin(PluginPtr);
return nullptr;
}
@@ -314,7 +321,7 @@ bool PluginManager::UnloadPlugin(Plugin* pPlugin, int From)

const auto IsPanelPlugin = pPlugin->IsPanelPlugin();

- Result = pPlugin->Unload(true);
+ Result = pPlugin->Unload();

pPlugin->WorkFlags.Set(PIWF_DONTLOADAGAIN);

@@ -353,7 +360,7 @@ bool PluginManager::UnloadPluginExternal(Plugin* pPlugin)
}

UnloadedPlugins.erase(pPlugin);
- const auto Result = pPlugin->Unload(true);
+ const auto Result = pPlugin->Unload();
RemovePlugin(pPlugin);
return Result;
}
@@ -2460,7 +2467,7 @@ void PluginManager::RefreshPluginsList()
if (i->Active())
return false;

- i->Unload(true);
+ i->Unload();
RemovePlugin(i);
return true;
});
diff --git a/far/vbuild.m4 b/far/vbuild.m4
index c52c7eb88..c6a9e34fa 100644
--- a/far/vbuild.m4
+++ b/far/vbuild.m4
@@ -1 +1 @@
-6660
+6661


Reply all
Reply to author
Forward
0 new messages