Separate plugin unloading into an eviction step, which disconnects the plugin from Core.
Note: this also ensures that library action callbacks are balanced (i.e., we do not notify libraries are being dropped if they were never notified as being added).
This commit is contained in:
parent
82ff7d5af7
commit
7cc911ae58
@ -56,6 +56,7 @@ CPlugin::CPlugin(const char *file)
|
|||||||
: m_serial(0),
|
: m_serial(0),
|
||||||
m_status(Plugin_Uncompiled),
|
m_status(Plugin_Uncompiled),
|
||||||
m_WaitingToUnload(false),
|
m_WaitingToUnload(false),
|
||||||
|
m_AddedLibraries(false),
|
||||||
m_SilentFailure(false),
|
m_SilentFailure(false),
|
||||||
m_FakeNativesMissing(false),
|
m_FakeNativesMissing(false),
|
||||||
m_LibraryMissing(false),
|
m_LibraryMissing(false),
|
||||||
@ -512,13 +513,17 @@ bool CPlugin::IsDebugging()
|
|||||||
|
|
||||||
void CPlugin::LibraryActions(LibraryAction action)
|
void CPlugin::LibraryActions(LibraryAction action)
|
||||||
{
|
{
|
||||||
List<String>::iterator iter;
|
if (action == LibraryAction_Removed) {
|
||||||
for (iter = m_Libraries.begin();
|
if (!m_AddedLibraries)
|
||||||
iter != m_Libraries.end();
|
return;
|
||||||
iter++)
|
m_AddedLibraries = false;
|
||||||
{
|
|
||||||
g_PluginSys.OnLibraryAction((*iter).c_str(), action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto iter = m_Libraries.begin(); iter != m_Libraries.end(); iter++)
|
||||||
|
g_PluginSys.OnLibraryAction((*iter).c_str(), action);
|
||||||
|
|
||||||
|
if (action == LibraryAction_Added)
|
||||||
|
m_AddedLibraries = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPlugin::SetPauseState(bool paused)
|
bool CPlugin::SetPauseState(bool paused)
|
||||||
@ -1284,9 +1289,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Go through our libraries and tell other plugins they're added */
|
/* Go through our libraries and tell other plugins they're added */
|
||||||
pPlugin->ForEachLibrary([this] (const char *lib) -> void {
|
pPlugin->LibraryActions(LibraryAction_Added);
|
||||||
OnLibraryAction(lib, LibraryAction_Added);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* :TODO: optimize? does this even matter? */
|
/* :TODO: optimize? does this even matter? */
|
||||||
pPlugin->GetPhrases()->AddPhraseFile("core.phrases");
|
pPlugin->GetPhrases()->AddPhraseFile("core.phrases");
|
||||||
@ -1391,33 +1394,32 @@ bool CPluginManager::ScheduleUnload(CPlugin *pPlugin)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPluginManager::UnloadPluginImpl(CPlugin *pPlugin)
|
void CPluginManager::Purge(CPlugin *plugin)
|
||||||
{
|
{
|
||||||
/* Remove us from the lookup table and linked list */
|
// Go through our libraries and tell other plugins they're gone.
|
||||||
m_plugins.remove(pPlugin);
|
plugin->LibraryActions(LibraryAction_Removed);
|
||||||
m_LoadLookup.remove(pPlugin->GetFilename());
|
|
||||||
|
|
||||||
/* Go through our libraries and tell other plugins they're gone */
|
if (plugin->GetStatus() <= Plugin_Error || plugin->GetStatus() == Plugin_Failed)
|
||||||
pPlugin->ForEachLibrary([this] (const char *lib) -> void {
|
|
||||||
OnLibraryAction(lib, LibraryAction_Removed);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pPlugin->GetStatus() <= Plugin_Error || pPlugin->GetStatus() == Plugin_Failed)
|
|
||||||
{
|
{
|
||||||
/* Notify plugin */
|
// Notify plugin.
|
||||||
pPlugin->Call_OnPluginEnd();
|
plugin->Call_OnPluginEnd();
|
||||||
|
|
||||||
/* Notify listeners of unloading */
|
// Notify listeners of unloading.
|
||||||
for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
|
for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
|
||||||
(*iter)->OnPluginUnloaded(pPlugin);
|
(*iter)->OnPluginUnloaded(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
pPlugin->DropEverything();
|
plugin->DropEverything();
|
||||||
|
|
||||||
for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
|
for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
|
||||||
(*iter)->OnPluginDestroyed(pPlugin);
|
(*iter)->OnPluginDestroyed(plugin);
|
||||||
|
}
|
||||||
/* Tell the plugin to delete itself */
|
|
||||||
|
void CPluginManager::UnloadPluginImpl(CPlugin *pPlugin)
|
||||||
|
{
|
||||||
|
m_plugins.remove(pPlugin);
|
||||||
|
m_LoadLookup.remove(pPlugin->GetFilename());
|
||||||
|
Purge(pPlugin);
|
||||||
delete pPlugin;
|
delete pPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ private:
|
|||||||
|
|
||||||
PluginStatus m_status;
|
PluginStatus m_status;
|
||||||
bool m_WaitingToUnload;
|
bool m_WaitingToUnload;
|
||||||
|
bool m_AddedLibraries;
|
||||||
|
|
||||||
// Statuses that are set during failure.
|
// Statuses that are set during failure.
|
||||||
bool m_SilentFailure;
|
bool m_SilentFailure;
|
||||||
@ -461,6 +462,8 @@ private:
|
|||||||
|
|
||||||
bool ScheduleUnload(CPlugin *plugin);
|
bool ScheduleUnload(CPlugin *plugin);
|
||||||
void UnloadPluginImpl(CPlugin *plugin);
|
void UnloadPluginImpl(CPlugin *plugin);
|
||||||
|
|
||||||
|
void Purge(CPlugin *plugin);
|
||||||
public:
|
public:
|
||||||
inline IdentityToken_t *GetIdentity()
|
inline IdentityToken_t *GetIdentity()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user