diff --git a/docs/release-notes.md b/docs/release-notes.md index 2e1e050e..2ff4ec0a 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,7 @@ ## Upcoming release * For players: * Fixed rare error when a mod adds/removes event handlers asynchronously. + * Removed the experimental `RewriteInParallel` option added in SMAPI 3.6 (it was already disabled by default). Unfortunately this caused intermittent unpredictable errors when enabled. * For modders: * You can now read/write `SDate` values to JSON (e.g. for `config.json`, network mod messages, etc). diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index f8c901e0..dbb5f696 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -76,10 +76,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// The mod for which the assembly is being loaded. /// The assembly file path. /// Assume the mod is compatible, even if incompatible code is detected. - /// Whether to enable experimental parallel rewriting. /// Returns the rewrite metadata for the preprocessed assembly. /// An incompatible CIL instruction was found while rewriting the assembly. - public Assembly Load(IModMetadata mod, string assemblyPath, bool assumeCompatible, bool rewriteInParallel) + public Assembly Load(IModMetadata mod, string assemblyPath, bool assumeCompatible) { // get referenced local assemblies AssemblyParseResult[] assemblies; @@ -109,7 +108,7 @@ namespace StardewModdingAPI.Framework.ModLoading continue; // rewrite assembly - bool changed = this.RewriteAssembly(mod, assembly.Definition, loggedMessages, logPrefix: " ", rewriteInParallel); + bool changed = this.RewriteAssembly(mod, assembly.Definition, loggedMessages, logPrefix: " "); // detect broken assembly reference foreach (AssemblyNameReference reference in assembly.Definition.MainModule.AssemblyReferences) @@ -263,10 +262,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// The assembly to rewrite. /// The messages that have already been logged for this mod. /// A string to prefix to log messages. - /// Whether to enable experimental parallel rewriting. /// Returns whether the assembly was modified. /// An incompatible CIL instruction was found while rewriting the assembly. - private bool RewriteAssembly(IModMetadata mod, AssemblyDefinition assembly, HashSet loggedMessages, string logPrefix, bool rewriteInParallel) + private bool RewriteAssembly(IModMetadata mod, AssemblyDefinition assembly, HashSet loggedMessages, string logPrefix) { ModuleDefinition module = assembly.MainModule; string filename = $"{assembly.Name.Name}.dll"; @@ -315,7 +313,7 @@ namespace StardewModdingAPI.Framework.ModLoading return rewritten; } ); - bool anyRewritten = rewriter.RewriteModule(rewriteInParallel); + bool anyRewritten = rewriter.RewriteModule(); // handle rewrite flags foreach (IInstructionHandler handler in handlers) diff --git a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs index 34c78c7d..fb651465 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; -using System.Threading.Tasks; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; @@ -57,59 +55,24 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework } /// Rewrite the loaded module code. - /// Whether to enable experimental parallel rewriting. /// Returns whether the module was modified. - public bool RewriteModule(bool rewriteInParallel) + public bool RewriteModule() { IEnumerable types = this.Module.GetTypes().Where(type => type.BaseType != null); // skip special types like - // experimental parallel rewriting - // This may cause intermittent startup errors and is disabled by default: https://github.com/Pathoschild/SMAPI/issues/721 - if (rewriteInParallel) + bool changed = false; + + try { - int typesChanged = 0; - Exception exception = null; - - Parallel.ForEach(types, type => - { - if (exception != null) - return; - - bool changed = false; - try - { - changed = this.RewriteTypeDefinition(type); - } - catch (Exception ex) - { - exception ??= ex; - } - - if (changed) - Interlocked.Increment(ref typesChanged); - }); - - return exception == null - ? typesChanged > 0 - : throw new Exception($"Rewriting {this.Module.Name} failed.", exception); + foreach (var type in types) + changed |= this.RewriteTypeDefinition(type); + } + catch (Exception ex) + { + throw new Exception($"Rewriting {this.Module.Name} failed.", ex); } - // non-parallel rewriting - { - bool changed = false; - - try - { - foreach (var type in types) - changed |= this.RewriteTypeDefinition(type); - } - catch (Exception ex) - { - throw new Exception($"Rewriting {this.Module.Name} failed.", ex); - } - - return changed; - } + return changed; } diff --git a/src/SMAPI/Framework/Models/SConfig.cs b/src/SMAPI/Framework/Models/SConfig.cs index 1c682f96..3a3f6960 100644 --- a/src/SMAPI/Framework/Models/SConfig.cs +++ b/src/SMAPI/Framework/Models/SConfig.cs @@ -16,7 +16,6 @@ namespace StardewModdingAPI.Framework.Models { [nameof(CheckForUpdates)] = true, [nameof(ParanoidWarnings)] = Constants.IsDebugBuild, - [nameof(RewriteInParallel)] = Constants.IsDebugBuild, [nameof(UseBetaChannel)] = Constants.ApiVersion.IsPrerelease(), [nameof(GitHubProjectName)] = "Pathoschild/SMAPI", [nameof(WebApiBaseUrl)] = "https://smapi.io/api/", @@ -41,9 +40,6 @@ namespace StardewModdingAPI.Framework.Models /// Whether to check for newer versions of SMAPI and mods on startup. public bool CheckForUpdates { get; set; } - /// Whether to enable experimental parallel rewriting. - public bool RewriteInParallel { get; set; } = (bool)SConfig.DefaultValues[nameof(SConfig.RewriteInParallel)]; - /// Whether to add a section to the 'mod issues' list for mods which which directly use potentially sensitive .NET APIs like file or shell access. public bool ParanoidWarnings { get; set; } = (bool)SConfig.DefaultValues[nameof(SConfig.ParanoidWarnings)]; diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 72ef9095..fd8d7034 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -337,8 +337,6 @@ namespace StardewModdingAPI.Framework // add headers if (this.Settings.DeveloperMode) this.Monitor.Log($"You have SMAPI for developers, so the console will be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing {Constants.ApiConfigPath}.", LogLevel.Info); - if (this.Settings.RewriteInParallel) - this.Monitor.Log($"You enabled experimental parallel rewriting. This may result in faster startup times, but intermittent startup errors. You can disable it by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Info); if (!this.Settings.CheckForUpdates) this.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Warn); if (!this.Monitor.WriteToConsole) @@ -983,7 +981,7 @@ namespace StardewModdingAPI.Framework Assembly modAssembly; try { - modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible, rewriteInParallel: this.Settings.RewriteInParallel); + modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible); this.ModRegistry.TrackAssemblies(mod, modAssembly); } catch (IncompatibleInstructionException) // details already in trace logs diff --git a/src/SMAPI/SMAPI.config.json b/src/SMAPI/SMAPI.config.json index 0a6d8372..6ba64fe7 100644 --- a/src/SMAPI/SMAPI.config.json +++ b/src/SMAPI/SMAPI.config.json @@ -33,15 +33,6 @@ copy all the settings, or you may cause bugs due to overridden changes in future */ "DeveloperMode": true, - /** - * Whether to enable experimental parallel rewriting when SMAPI is loading mods. This can - * reduce startup time when you have many mods installed, but is experimental and may cause - * intermittent startup errors. - * - * When this is commented out, it'll be true for local debug builds and false otherwise. - */ - //"RewriteInParallel": false, - /** * Whether to add a section to the 'mod issues' list for mods which directly use potentially * sensitive .NET APIs like file or shell access. Note that many mods do this legitimately as