Improve detection of plugin bricking an install on startup (#4533)

This commit is contained in:
Nicolas Dorier 2023-01-18 14:15:27 +09:00 committed by GitHub
parent b5cd215643
commit 1228a06a90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 9 deletions

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
@ -24,9 +25,29 @@ namespace BTCPayServer.Plugins
public const string BTCPayPluginSuffix = ".btcpay"; public const string BTCPayPluginSuffix = ".btcpay";
private static readonly List<Assembly> _pluginAssemblies = new List<Assembly>(); private static readonly List<Assembly> _pluginAssemblies = new List<Assembly>();
public static bool IsExceptionByPlugin(Exception exception) public static bool IsExceptionByPlugin(Exception exception, [MaybeNullWhen(false)] out string pluginName)
{ {
return _pluginAssemblies.Any(assembly => assembly?.FullName?.Contains(exception.Source!, StringComparison.OrdinalIgnoreCase) is true); foreach (var assembly in _pluginAssemblies)
{
var assemblyName = assembly.GetName().Name;
if (assemblyName is null)
continue;
// Comparison is case sensitive as it is theorically possible to have a different plugin
// with same name but different casing.
if (exception.Source is not null &&
assemblyName.Equals(exception.Source, StringComparison.Ordinal))
{
pluginName = assemblyName;
return true;
}
if (exception.Message.Contains(assemblyName, StringComparison.Ordinal))
{
pluginName = assemblyName;
return true;
}
}
pluginName = null;
return false;
} }
public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection, public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection,
IConfiguration config, ILoggerFactory loggerFactory) IConfiguration config, ILoggerFactory loggerFactory)
@ -51,14 +72,14 @@ namespace BTCPayServer.Plugins
// as the assembly. Except for the system assembly (btcpayserver assembly) which are fake plugins // as the assembly. Except for the system assembly (btcpayserver assembly) which are fake plugins
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{ {
var pluginIdentifier = assembly.GetName().Name; var assemblyName = assembly.GetName().Name;
bool isSystemPlugin = assembly == systemAssembly; bool isSystemPlugin = assembly == systemAssembly;
if (!isSystemPlugin && disabledPlugins.Contains(pluginIdentifier)) if (!isSystemPlugin && disabledPlugins.Contains(assemblyName))
continue; continue;
foreach (var plugin in GetPluginInstancesFromAssembly(assembly)) foreach (var plugin in GetPluginInstancesFromAssembly(assembly))
{ {
if (!isSystemPlugin && plugin.Identifier != pluginIdentifier) if (!isSystemPlugin && plugin.Identifier != assemblyName)
continue; continue;
if (!loadedPluginIdentifiers.Add(plugin.Identifier)) if (!loadedPluginIdentifiers.Add(plugin.Identifier))
continue; continue;
@ -150,7 +171,6 @@ namespace BTCPayServer.Plugins
$"Error when loading plugin {plugin.Identifier} - {plugin.Version}{Environment.NewLine}{e.Message}"); $"Error when loading plugin {plugin.Identifier} - {plugin.Version}{Environment.NewLine}{e.Message}");
} }
} }
return mvcBuilder; return mvcBuilder;
} }

View file

@ -85,11 +85,11 @@ namespace BTCPayServer
if (!string.IsNullOrEmpty(ex.Message)) if (!string.IsNullOrEmpty(ex.Message))
logs.Configuration.LogError(ex.Message); logs.Configuration.LogError(ex.Message);
} }
catch (Exception e) when (PluginManager.IsExceptionByPlugin(e)) catch (Exception e) when (PluginManager.IsExceptionByPlugin(e, out var pluginName))
{ {
logs.Configuration.LogError(e, $"Disabling plugin {e.Source} as it crashed on startup"); logs.Configuration.LogError(e, $"Disabling plugin {pluginName} as it crashed on startup");
var pluginDir = new DataDirectories().Configure(conf).PluginDir; var pluginDir = new DataDirectories().Configure(conf).PluginDir;
PluginManager.DisablePlugin(pluginDir, e.Source); PluginManager.DisablePlugin(pluginDir, pluginName);
} }
finally finally
{ {