From 7c2fbec77386767dc35dc1ef24d6a725d1aaad94 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sat, 28 Dec 2019 14:00:48 -0800 Subject: [PATCH] Fix proxy object timeout in visualization editor The visualization editor was retaining an IPlugin reference for the visualization generator selection combo box. After 5 minutes the proxy object timed out, so if you left the editor open and inactive for that long you'd start getting weird errors. We now keep the script identifier string and use that to get a fresh IPlugin proxy object. --- PluginCommon/PluginManager.cs | 12 +++-- SourceGen/DisasmProject.cs | 5 +- SourceGen/Sandbox/ScriptManager.cs | 46 ++++++++++--------- SourceGen/VisualizationSet.cs | 8 ++-- SourceGen/WpfGui/EditVisualization.xaml.cs | 25 +++++----- SourceGen/WpfGui/EditVisualizationSet.xaml.cs | 4 +- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/PluginCommon/PluginManager.cs b/PluginCommon/PluginManager.cs index 8a5d847..754e83e 100644 --- a/PluginCommon/PluginManager.cs +++ b/PluginCommon/PluginManager.cs @@ -132,14 +132,16 @@ namespace PluginCommon { /// Generates a list of references to instances of active plugins. /// /// Newly-created list of plugin references. - public List GetActivePlugins() { - List list = new List(mActivePlugins.Count); + public Dictionary GetActivePlugins() { + Dictionary dict = + new Dictionary(mActivePlugins.Count); foreach (KeyValuePair kvp in mActivePlugins) { - list.Add(kvp.Value); + // copy the contents; probably not necessary across AppDomain + dict.Add(kvp.Key, kvp.Value); } - Debug.WriteLine("PluginManager: returning " + list.Count + " plugins (id=" + + Debug.WriteLine("PluginManager: returning " + dict.Count + " plugins (id=" + AppDomain.CurrentDomain.Id + ")"); - return list; + return dict; } /// diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs index 3787c56..ef43cf2 100644 --- a/SourceGen/DisasmProject.cs +++ b/SourceGen/DisasmProject.cs @@ -2496,9 +2496,12 @@ namespace SourceGen { } // Punch-through functions; trying to avoid exposing ScriptManager for now. - public List GetActivePlugins() { + public Dictionary GetActivePlugins() { return mScriptManager.GetActivePlugins(); } + public PluginCommon.IPlugin GetPlugin(string scriptIdent) { + return mScriptManager.GetInstance(scriptIdent); + } public void PrepareScripts(PluginCommon.IApplication appRef) { mScriptManager.PrepareScripts(appRef); } diff --git a/SourceGen/Sandbox/ScriptManager.cs b/SourceGen/Sandbox/ScriptManager.cs index 931ebf0..1bb53ec 100644 --- a/SourceGen/Sandbox/ScriptManager.cs +++ b/SourceGen/Sandbox/ScriptManager.cs @@ -140,15 +140,17 @@ namespace SourceGen.Sandbox { /// /// Newly-created list of plugin references. public List GetAllInstances() { + Dictionary dict; if (DomainMgr == null) { - List list = new List(mActivePlugins.Count); - foreach (KeyValuePair kvp in mActivePlugins) { - list.Add(kvp.Value); - } - return list; + dict = mActivePlugins; } else { - return DomainMgr.PluginMgr.GetActivePlugins(); + dict = DomainMgr.PluginMgr.GetActivePlugins(); } + List list = new List(dict.Count); + foreach (KeyValuePair kvp in dict) { + list.Add(kvp.Value); + } + return list; } /// @@ -272,36 +274,36 @@ namespace SourceGen.Sandbox { return plSymbols; } +#if false public delegate bool CheckMatch(IPlugin plugin); public IPlugin GetMatchingScript(CheckMatch check) { + Dictionary plugins; if (DomainMgr == null) { - foreach (KeyValuePair kvp in mActivePlugins) { - if (check(kvp.Value)) { - return kvp.Value; - } - } + plugins = mActivePlugins; } else { - List plugins = DomainMgr.PluginMgr.GetActivePlugins(); - foreach (IPlugin plugin in plugins) { - if (check(plugin)) { - return plugin; - } + plugins = DomainMgr.PluginMgr.GetActivePlugins(); + } + foreach (IPlugin plugin in plugins.Values) { + if (check(plugin)) { + return plugin; } } return null; } +#endif /// /// Returns a list of loaded plugins. Callers should not retain this list, as the /// set can change due to user activity. /// - public List GetActivePlugins() { + public Dictionary GetActivePlugins() { if (DomainMgr == null) { - List plist = new List(); + // copy the contents + Dictionary pdict = new Dictionary(); foreach (KeyValuePair kvp in mActivePlugins) { - plist.Add(kvp.Value); + pdict.Add(kvp.Key, kvp.Value); } - return plist; + return pdict; } else { return DomainMgr.PluginMgr.GetActivePlugins(); } @@ -322,8 +324,8 @@ namespace SourceGen.Sandbox { DebugGetScriptInfo(kvp.Value, sb); } } else { - List plugins = DomainMgr.PluginMgr.GetActivePlugins(); - foreach (IPlugin plugin in plugins) { + Dictionary plugins = DomainMgr.PluginMgr.GetActivePlugins(); + foreach (IPlugin plugin in plugins.Values) { string loc = DomainMgr.PluginMgr.GetPluginAssemblyLocation(plugin); sb.AppendFormat("[sub {0}] ", DomainMgr.Id); sb.Append(loc); diff --git a/SourceGen/VisualizationSet.cs b/SourceGen/VisualizationSet.cs index 51581ea..5887236 100644 --- a/SourceGen/VisualizationSet.cs +++ b/SourceGen/VisualizationSet.cs @@ -174,7 +174,7 @@ namespace SourceGen { /// Project reference. public static void RefreshAllThumbnails(DisasmProject project) { ScriptSupport iapp = null; - List plugins = null; + Dictionary plugins = null; SortedList visSets = project.VisualizationSets; @@ -248,9 +248,9 @@ namespace SourceGen { /// List of plugins, from project ScriptManager. /// Visualization generator identifier. /// A plugin that matches, or null if none found. - private static IPlugin_Visualizer FindPluginByVisGenIdent(List plugins, - string visGenIdent, out VisDescr visDescr) { - foreach (IPlugin chkPlug in plugins) { + private static IPlugin_Visualizer FindPluginByVisGenIdent( + Dictionary plugins, string visGenIdent, out VisDescr visDescr) { + foreach (IPlugin chkPlug in plugins.Values) { if (!(chkPlug is IPlugin_Visualizer)) { continue; } diff --git a/SourceGen/WpfGui/EditVisualization.xaml.cs b/SourceGen/WpfGui/EditVisualization.xaml.cs index 7cc90c8..9d87002 100644 --- a/SourceGen/WpfGui/EditVisualization.xaml.cs +++ b/SourceGen/WpfGui/EditVisualization.xaml.cs @@ -84,13 +84,15 @@ namespace SourceGen.WpfGui { /// /// /// Strictly speaking we could just create an ItemsSource from VisDescr objects, but - /// the plugin reference saves a lookup later. + /// the plugin reference saves a lookup later. We store the script ident rather than + /// an IPlugin reference because our reference would be a proxy object that expires, + /// and there's no value in creating a Sponsor<> or playing keep-alive. /// public class VisualizationItem { - public IPlugin_Visualizer Plugin { get; private set; } + public string ScriptIdent { get; private set; } public VisDescr VisDescriptor { get; private set; } - public VisualizationItem(IPlugin_Visualizer plugin, VisDescr descr) { - Plugin = plugin; + public VisualizationItem(string scriptIdent, VisDescr descr) { + ScriptIdent = scriptIdent; VisDescriptor = descr; } } @@ -198,12 +200,12 @@ namespace SourceGen.WpfGui { int visSelection = -1; VisualizationList = new List(); - List plugins = proj.GetActivePlugins(); - foreach (IPlugin chkPlug in plugins) { - if (!(chkPlug is IPlugin_Visualizer)) { + Dictionary plugins = proj.GetActivePlugins(); + foreach (KeyValuePair kvp in plugins) { + if (!(kvp.Value is IPlugin_Visualizer)) { continue; } - IPlugin_Visualizer vplug = (IPlugin_Visualizer)chkPlug; + IPlugin_Visualizer vplug = (IPlugin_Visualizer)kvp.Value; foreach (VisDescr descr in vplug.GetVisGenDescrs()) { if (vis != null && vis.VisGenIdent == descr.Ident) { // found matching descriptor, set selection to this @@ -212,7 +214,7 @@ namespace SourceGen.WpfGui { // we used this one last time, use it if nothing better comes along visSelection = VisualizationList.Count; } - VisualizationList.Add(new VisualizationItem(vplug, descr)); + VisualizationList.Add(new VisualizationItem(kvp.Key, descr)); } } @@ -437,8 +439,9 @@ namespace SourceGen.WpfGui { IVisualization2d vis2d; try { - vis2d = item.Plugin.Generate2d(item.VisDescriptor, - CreateVisGenParams()); + IPlugin_Visualizer plugin = + (IPlugin_Visualizer)mProject.GetPlugin(item.ScriptIdent); + vis2d = plugin.Generate2d(item.VisDescriptor, CreateVisGenParams()); if (vis2d == null) { Debug.WriteLine("Vis generator returned null"); } diff --git a/SourceGen/WpfGui/EditVisualizationSet.xaml.cs b/SourceGen/WpfGui/EditVisualizationSet.xaml.cs index f75828b..9b72f34 100644 --- a/SourceGen/WpfGui/EditVisualizationSet.xaml.cs +++ b/SourceGen/WpfGui/EditVisualizationSet.xaml.cs @@ -125,8 +125,8 @@ namespace SourceGen.WpfGui { } // Check to see if we have any relevant plugins. If not, disable New/Edit. - List plugins = project.GetActivePlugins(); - foreach (IPlugin chkPlug in plugins) { + Dictionary plugins = project.GetActivePlugins(); + foreach (IPlugin chkPlug in plugins.Values) { if (chkPlug is IPlugin_Visualizer) { HasVisPlugins = true; break;