diff options
author | Lluis Sanchez <llsan@microsoft.com> | 2022-06-14 02:56:25 +0300 |
---|---|---|
committer | Lluis Sanchez <llsan@microsoft.com> | 2022-09-13 20:38:42 +0300 |
commit | 86b644dd323c725888d09cb53423fe430fc684a9 (patch) | |
tree | 60d547c42a106c53dcfd71bbcb1e5019836cc148 | |
parent | 8b5552652a0d6d8816053fd9c4cae5c697e55dec (diff) |
More thread safety
-rw-r--r-- | Mono.Addins/Mono.Addins/Addin.cs | 33 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinEngine.cs | 12 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinInfo.cs | 37 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinRegistry.cs | 43 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionContextTransaction.cs | 2 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionNode.cs | 10 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionTree.cs | 2 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/InstanceExtensionNode.cs | 9 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/RuntimeAddin.cs | 45 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/TreeNode.cs | 4 |
10 files changed, 99 insertions, 98 deletions
diff --git a/Mono.Addins/Mono.Addins/Addin.cs b/Mono.Addins/Mono.Addins/Addin.cs index 47f9917..792eb84 100644 --- a/Mono.Addins/Mono.Addins/Addin.cs +++ b/Mono.Addins/Mono.Addins/Addin.cs @@ -136,14 +136,16 @@ namespace Mono.Addins internal AddinInfo AddinInfo { get { - if (addin == null) { + var addinInfo = addin; + + if (addinInfo == null) { try { - addin = AddinInfo.ReadFromDescription (Description); + addinInfo = addin = AddinInfo.ReadFromDescription (Description); } catch (Exception ex) { throw new InvalidOperationException ("Could not read add-in file: " + database.GetDescriptionPath (domain, id), ex); } } - return addin; + return addinInfo; } } @@ -235,17 +237,16 @@ namespace Mono.Addins /// </summary> public AddinDescription Description { get { - if (desc != null) { - AddinDescription d = desc.Target as AddinDescription; - if (d != null) - return d; + var addinDescription = (AddinDescription) desc?.Target; + if (addinDescription != null) { + return addinDescription; } var configFile = database.GetDescriptionPath (domain, id); - AddinDescription m; - database.ReadAddinDescription (new ConsoleProgressStatus (true), configFile, out m); - if (m == null) { + database.ReadAddinDescription (new ConsoleProgressStatus (true), configFile, out addinDescription); + + if (addinDescription == null) { try { if (File.Exists (configFile)) { // The file is corrupted. Remove it. @@ -257,14 +258,14 @@ namespace Mono.Addins throw new InvalidOperationException ("Could not read add-in description"); } if (addin == null) { - addin = AddinInfo.ReadFromDescription (m); - sourceFile = m.AddinFile; + addin = AddinInfo.ReadFromDescription (addinDescription); + sourceFile = addinDescription.AddinFile; } - SetIsUserAddin (m); + SetIsUserAddin (addinDescription); if (!isUserAddin.Value) - m.Flags |= AddinFlags.CantUninstall; - desc = new WeakReference (m); - return m; + addinDescription.Flags |= AddinFlags.CantUninstall; + desc = new WeakReference (addinDescription); + return addinDescription; } } diff --git a/Mono.Addins/Mono.Addins/AddinEngine.cs b/Mono.Addins/Mono.Addins/AddinEngine.cs index d6adb62..1e0a615 100644 --- a/Mono.Addins/Mono.Addins/AddinEngine.cs +++ b/Mono.Addins/Mono.Addins/AddinEngine.cs @@ -247,7 +247,7 @@ namespace Mono.Addins if (string.IsNullOrEmpty (configDir)) registry = AddinRegistry.GetGlobalRegistry (this, startupDirectory); else - registry = new AddinRegistry (this, configDir, startupDirectory, addinsDir, databaseDir); + registry = new AddinRegistry (this, configDir, startupDirectory, addinsDir, databaseDir, null); if ((asmFile != null && registry.CreateHostAddinsFile (asmFile)) || registry.UnknownDomain) registry.Update (new ConsoleProgressStatus (false)); @@ -590,20 +590,18 @@ namespace Mono.Addins bool InsertAddin (ExtensionContextTransaction transaction, IProgressStatus statusMonitor, Addin iad) { try { - RuntimeAddin runtimeAddin = new RuntimeAddin (this); + RuntimeAddin runtimeAddin = new RuntimeAddin (this, iad); + AddinDescription description = iad.Description; RegisterAssemblyResolvePaths (transaction, runtimeAddin, iad.Description.MainModule); - - // Read the config file and load the add-in assemblies - AddinDescription description = runtimeAddin.Load (iad); - + // Register the add-in loadedAddins = loadedAddins.SetItem(Addin.GetIdName (runtimeAddin.Id), runtimeAddin); if (!AddinDatabase.RunningSetupProcess) { // Load the extension points and other addin data - RegisterNodeSets (iad.Id, description.ExtensionNodeSets); + RegisterNodeSets (transaction, iad.Id, description.ExtensionNodeSets); foreach (ConditionTypeDescription cond in description.ConditionTypes) RegisterCondition (transaction, cond.Id, runtimeAddin, cond.TypeName); diff --git a/Mono.Addins/Mono.Addins/AddinInfo.cs b/Mono.Addins/Mono.Addins/AddinInfo.cs index b1125f7..eb8f127 100644 --- a/Mono.Addins/Mono.Addins/AddinInfo.cs +++ b/Mono.Addins/Mono.Addins/AddinInfo.cs @@ -32,6 +32,8 @@ using System.Collections; using System.Xml; using System.Xml.Serialization; using Mono.Addins.Description; +using System.Collections.Immutable; +using System.Linq; namespace Mono.Addins { @@ -49,14 +51,14 @@ namespace Mono.Addins string category = ""; bool defaultEnabled = true; bool isroot; - DependencyCollection dependencies; - DependencyCollection optionalDependencies; + ImmutableArray<Dependency> dependencies; + ImmutableArray<Dependency> optionalDependencies; AddinPropertyCollection properties; private AddinInfo () { - dependencies = new DependencyCollection (); - optionalDependencies = new DependencyCollection (); + dependencies = ImmutableArray<Dependency>.Empty; + optionalDependencies = ImmutableArray<Dependency>.Empty; } public string Id { @@ -65,17 +67,14 @@ namespace Mono.Addins public string LocalId { get { return id; } - set { id = value; } } public string Namespace { get { return namspace; } - set { namspace = value; } } public bool IsRoot { get { return isroot; } - set { isroot = value; } } public string Name { @@ -90,17 +89,14 @@ namespace Mono.Addins sid = sid.Substring (2); return Addin.GetFullId (namspace, sid, null); } - set { name = value; } } public string Version { get { return version; } - set { version = value; } } public string BaseVersion { get { return baseVersion; } - set { baseVersion = value; } } public string Author { @@ -110,7 +106,6 @@ namespace Mono.Addins return s; return author; } - set { author = value; } } public string Copyright { @@ -120,7 +115,6 @@ namespace Mono.Addins return s; return copyright; } - set { copyright = value; } } public string Url { @@ -130,7 +124,6 @@ namespace Mono.Addins return s; return url; } - set { url = value; } } public string Description { @@ -140,7 +133,6 @@ namespace Mono.Addins return s; return description; } - set { description = value; } } public string Category { @@ -150,19 +142,17 @@ namespace Mono.Addins return s; return category; } - set { category = value; } } public bool EnabledByDefault { get { return defaultEnabled; } - set { defaultEnabled = value; } } - public DependencyCollection Dependencies { + public ImmutableArray<Dependency> Dependencies { get { return dependencies; } } - public DependencyCollection OptionalDependencies { + public ImmutableArray<Dependency> OptionalDependencies { get { return optionalDependencies; } } @@ -185,14 +175,9 @@ namespace Mono.Addins info.baseVersion = description.CompatVersion; info.isroot = description.IsRoot; info.defaultEnabled = description.EnabledByDefault; - - foreach (Dependency dep in description.MainModule.Dependencies) - info.Dependencies.Add (dep); - - foreach (ModuleDescription mod in description.OptionalModules) { - foreach (Dependency dep in mod.Dependencies) - info.OptionalDependencies.Add (dep); - } + + info.dependencies = ImmutableArray<Dependency>.Empty.AddRange (description.MainModule.Dependencies); + info.optionalDependencies = ImmutableArray<Dependency>.Empty.AddRange (description.OptionalModules.SelectMany(module => module.Dependencies)); info.properties = description.Properties; return info; diff --git a/Mono.Addins/Mono.Addins/AddinRegistry.cs b/Mono.Addins/Mono.Addins/AddinRegistry.cs index 0e1ef2a..94e8123 100644 --- a/Mono.Addins/Mono.Addins/AddinRegistry.cs +++ b/Mono.Addins/Mono.Addins/AddinRegistry.cs @@ -67,13 +67,13 @@ namespace Mono.Addins /// </remarks> public class AddinRegistry: IDisposable { - AddinDatabase database; - StringCollection addinDirs; - string basePath; + readonly AddinDatabase database; + readonly string [] addinDirs; + readonly string basePath; + readonly string startupDirectory; + readonly string addinsDir; + readonly string databaseDir; string currentDomain; - string startupDirectory; - string addinsDir; - string databaseDir; /// <summary> /// Initializes a new instance. @@ -92,7 +92,7 @@ namespace Mono.Addins /// of the Environment.SpecialFolder enumeration can be used (always between square /// brackets) /// </remarks> - public AddinRegistry (string registryPath): this (null, registryPath, null, null, null) + public AddinRegistry (string registryPath): this (null, registryPath, null, null, null, null) { } @@ -116,7 +116,7 @@ namespace Mono.Addins /// of the Environment.SpecialFolder enumeration can be used (always between square /// brackets) /// </remarks> - public AddinRegistry (string registryPath, string startupDirectory): this (null, registryPath, startupDirectory, null, null) + public AddinRegistry (string registryPath, string startupDirectory): this (null, registryPath, startupDirectory, null, null, null) { } @@ -145,7 +145,7 @@ namespace Mono.Addins /// of the Environment.SpecialFolder enumeration can be used (always between square /// brackets) /// </remarks> - public AddinRegistry (string registryPath, string startupDirectory, string addinsDir): this (null, registryPath, startupDirectory, addinsDir, null) + public AddinRegistry (string registryPath, string startupDirectory, string addinsDir): this (null, registryPath, startupDirectory, addinsDir, null, null) { } @@ -179,11 +179,11 @@ namespace Mono.Addins /// of the Environment.SpecialFolder enumeration can be used (always between square /// brackets) /// </remarks> - public AddinRegistry (string registryPath, string startupDirectory, string addinsDir, string databaseDir): this (null, registryPath, startupDirectory, addinsDir, databaseDir) + public AddinRegistry (string registryPath, string startupDirectory, string addinsDir, string databaseDir): this (null, registryPath, startupDirectory, addinsDir, databaseDir, null) { } - internal AddinRegistry (AddinEngine engine, string registryPath, string startupDirectory, string addinsDir, string databaseDir) + internal AddinRegistry (AddinEngine engine, string registryPath, string startupDirectory, string addinsDir, string databaseDir, string additionalGlobalAddinDirectory) { basePath = Path.GetFullPath (Util.NormalizePath (registryPath)); @@ -208,8 +208,10 @@ namespace Mono.Addins // Look for add-ins in the hosts directory and in the default // addins directory - addinDirs = new StringCollection (); - addinDirs.Add (DefaultAddinsFolder); + if (additionalGlobalAddinDirectory != null) + addinDirs = new [] { DefaultAddinsFolder, additionalGlobalAddinDirectory }; + else + addinDirs = new [] { DefaultAddinsFolder }; // Initialize the database after all paths have been set database = new AddinDatabase (engine, this); @@ -239,15 +241,15 @@ namespace Mono.Addins internal static AddinRegistry GetGlobalRegistry (AddinEngine engine, string startupDirectory) { - AddinRegistry reg = new AddinRegistry (engine, GlobalRegistryPath, startupDirectory, null, null); string baseDir; if (Util.IsWindows) baseDir = Environment.GetFolderPath (Environment.SpecialFolder.CommonProgramFiles); else baseDir = "/etc"; - - reg.GlobalAddinDirectories.Add (Path.Combine (baseDir, "mono.addins")); - return reg; + + var globalDir = Path.Combine (baseDir, "mono.addins"); + + return new AddinRegistry (engine, GlobalRegistryPath, startupDirectory, null, null, globalDir); } internal bool UnknownDomain { @@ -743,10 +745,15 @@ namespace Mono.Addins get { return databaseDir; } } - internal StringCollection GlobalAddinDirectories { + internal IEnumerable<string> GlobalAddinDirectories { get { return addinDirs; } } + internal void RegisterGlobalAddinDirectory (string dir) + { + + } + internal string StartupDirectory { get { return startupDirectory; diff --git a/Mono.Addins/Mono.Addins/ExtensionContextTransaction.cs b/Mono.Addins/Mono.Addins/ExtensionContextTransaction.cs index 7ca7eed..f961d8c 100644 --- a/Mono.Addins/Mono.Addins/ExtensionContextTransaction.cs +++ b/Mono.Addins/Mono.Addins/ExtensionContextTransaction.cs @@ -185,7 +185,7 @@ namespace Mono.Addins public void ReportAddinLoad (RuntimeAddin addin) { if (addinLoadEvents == null) - addinLoadEvents = new List<string> (); + addinLoadEvents = new List<RuntimeAddin> (); addinLoadEvents.Add (addin); } diff --git a/Mono.Addins/Mono.Addins/ExtensionNode.cs b/Mono.Addins/Mono.Addins/ExtensionNode.cs index 5452dcd..dc490bc 100644 --- a/Mono.Addins/Mono.Addins/ExtensionNode.cs +++ b/Mono.Addins/Mono.Addins/ExtensionNode.cs @@ -61,7 +61,7 @@ namespace Mono.Addins ModuleDescription module; AddinEngine addinEngine; event ExtensionNodeEventHandler extensionNodeChanged; - object localLock = new object (); + internal readonly object localLock = new object (); /// <summary> /// Identifier of the node. @@ -121,11 +121,19 @@ namespace Mono.Addins internal void SetTreeNode (TreeNode node) { + // treeNode can only be set once (it's set during the node initialization) + if (treeNode != null) + throw new InvalidOperationException (); + treeNode = node; } internal void SetData (AddinEngine addinEngine, string plugid, ExtensionNodeType nodeType, ModuleDescription module) { + // SetData can only be called once (it's set during the node initialization) + if (addinEngine != null) + throw new InvalidOperationException (); + this.addinEngine = addinEngine; this.addinId = plugid; this.nodeType = nodeType; diff --git a/Mono.Addins/Mono.Addins/ExtensionTree.cs b/Mono.Addins/Mono.Addins/ExtensionTree.cs index 3b571a4..b8da472 100644 --- a/Mono.Addins/Mono.Addins/ExtensionTree.cs +++ b/Mono.Addins/Mono.Addins/ExtensionTree.cs @@ -41,7 +41,7 @@ namespace Mono.Addins { int internalId; internal const string AutoIdPrefix = "__nid_"; - ExtensionContext context; + readonly ExtensionContext context; public ExtensionTree (AddinEngine addinEngine, ExtensionContext context): base (addinEngine, "") { diff --git a/Mono.Addins/Mono.Addins/InstanceExtensionNode.cs b/Mono.Addins/Mono.Addins/InstanceExtensionNode.cs index 3d6640d..e49632e 100644 --- a/Mono.Addins/Mono.Addins/InstanceExtensionNode.cs +++ b/Mono.Addins/Mono.Addins/InstanceExtensionNode.cs @@ -69,8 +69,13 @@ namespace Mono.Addins /// </remarks> public object GetInstance () { - if (cachedInstance == null) - cachedInstance = CreateInstance (); + if (cachedInstance == null) { + lock (localLock) { + // Use locking here to avoid creating more than one instance per ExtensionNode + if (cachedInstance != null) + cachedInstance = CreateInstance (); + } + } return cachedInstance; } diff --git a/Mono.Addins/Mono.Addins/RuntimeAddin.cs b/Mono.Addins/Mono.Addins/RuntimeAddin.cs index 54d1749..d5a03ac 100644 --- a/Mono.Addins/Mono.Addins/RuntimeAddin.cs +++ b/Mono.Addins/Mono.Addins/RuntimeAddin.cs @@ -49,27 +49,37 @@ namespace Mono.Addins /// </summary> public class RuntimeAddin { - string id; - string baseDirectory; + readonly string id; + readonly string baseDirectory; + readonly Addin ainfo; + readonly RuntimeAddin parentAddin; + readonly AddinEngine addinEngine; + readonly ModuleDescription module; + string privatePath; - Addin ainfo; - RuntimeAddin parentAddin; Dictionary<string, Assembly> loadedAssemblies = new Dictionary<string, Assembly>(); bool fullyLoadedAssemblies; - - RuntimeAddin[] depAddins; - ResourceManager[] resourceManagers; + + RuntimeAddin [] depAddins; + ResourceManager [] resourceManagers; AddinLocalizer localizer; - ModuleDescription module; - AddinEngine addinEngine; ExtensionNodeDescription localizerDescription; - internal RuntimeAddin (AddinEngine addinEngine) + internal RuntimeAddin (AddinEngine addinEngine, Addin iad) { this.addinEngine = addinEngine; + + ainfo = iad; + + AddinDescription description = iad.Description; + id = description.AddinId; + baseDirectory = description.BasePath; + module = description.MainModule; + module.RuntimeAddin = this; + localizerDescription = description.Localizer; } - + internal RuntimeAddin (AddinEngine addinEngine, RuntimeAddin parentAddin, ModuleDescription module) { this.addinEngine = addinEngine; @@ -619,19 +629,6 @@ namespace Mono.Addins return addin; } - internal AddinDescription Load (Addin iad) - { - ainfo = iad; - - AddinDescription description = iad.Description; - id = description.AddinId; - baseDirectory = description.BasePath; - module = description.MainModule; - module.RuntimeAddin = this; - localizerDescription = description.Localizer; - return description; - } - AddinLocalizer LoadLocalizer () { if (localizerDescription != null) { diff --git a/Mono.Addins/Mono.Addins/TreeNode.cs b/Mono.Addins/Mono.Addins/TreeNode.cs index 827545c..8cccdab 100644 --- a/Mono.Addins/Mono.Addins/TreeNode.cs +++ b/Mono.Addins/Mono.Addins/TreeNode.cs @@ -42,12 +42,12 @@ namespace Mono.Addins ImmutableArray<TreeNode> children; ExtensionNode extensionNode; bool childrenLoaded; - string id; + readonly string id; TreeNode parent; ExtensionNodeSet nodeTypes; ExtensionPoint extensionPoint; BaseCondition condition; - protected AddinEngine addinEngine; + protected readonly AddinEngine addinEngine; public TreeNode (AddinEngine addinEngine, string id) { |