- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1k
Fix plugin exception #3426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix plugin exception #3426
Changes from 18 commits
a7f39ef
              ffcd7ce
              a4cade1
              5ebdfd4
              82fcfb6
              da31567
              ba3e748
              0a41a97
              b76adb9
              5a7443f
              c9e6dd4
              3944f42
              79d597c
              5034e7f
              b384811
              2ecf454
              1a80344
              e4b10cb
              07906b2
              eb0c6b4
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -16,6 +16,7 @@ | |
| using Neo.Network.P2P; | ||
| using Neo.Network.P2P.Payloads; | ||
| using Neo.Persistence; | ||
| using Neo.Plugins; | ||
| using Neo.SmartContract; | ||
| using Neo.SmartContract.Native; | ||
| using Neo.VM; | ||
|  | @@ -24,6 +25,7 @@ | |
| using System.Collections.Immutable; | ||
| using System.Diagnostics; | ||
| using System.Linq; | ||
| using System.Runtime.CompilerServices; | ||
|  | ||
| namespace Neo.Ledger | ||
| { | ||
|  | @@ -468,10 +470,10 @@ private void Persist(Block block) | |
| Context.System.EventStream.Publish(application_executed); | ||
| all_application_executed.Add(application_executed); | ||
| } | ||
| Committing?.Invoke(system, block, snapshot, all_application_executed); | ||
| InvokeCommitting(system, block, snapshot, all_application_executed); | ||
| snapshot.Commit(); | ||
| } | ||
| Committed?.Invoke(system, block); | ||
| InvokeCommitted(system, block); | ||
| system.MemPool.UpdatePoolForBlockPersisted(block, system.StoreView); | ||
| extensibleWitnessWhiteList = null; | ||
| block_cache.Remove(block.PrevHash); | ||
|  | @@ -480,6 +482,56 @@ private void Persist(Block block) | |
| Debug.Assert(header.Index == block.Index); | ||
| } | ||
|  | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| internal static void InvokeCommitting(NeoSystem system, Block block, DataCache snapshot, IReadOnlyList<ApplicationExecuted> applicationExecutedList) | ||
| { | ||
| InvokeHandlers(Committing?.GetInvocationList(), h => ((CommittingHandler)h)(system, block, snapshot, applicationExecutedList)); | ||
| } | ||
|  | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| internal static void InvokeCommitted(NeoSystem system, Block block) | ||
| { | ||
| InvokeHandlers(Committed?.GetInvocationList(), h => ((CommittedHandler)h)(system, block)); | ||
| } | ||
|  | ||
| private static void InvokeHandlers(Delegate[] handlers, Action<Delegate> handlerAction) | ||
| { | ||
| if (handlers == null) return; | ||
|  | ||
| foreach (var handler in handlers) | ||
| { | ||
| try | ||
| { | ||
| // skip stopped plugin. | ||
| if (handler.Target is Plugin { IsStopped: true }) | ||
| { | ||
| continue; | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the stopped plugin keep crashing nothing will be reported? | ||
| } | ||
|  | ||
| handlerAction(handler); | ||
| } | ||
| catch (Exception ex) when (handler.Target is Plugin plugin) | ||
| { | ||
| Utility.Log(nameof(plugin), LogLevel.Error, ex); | ||
| switch (plugin.ExceptionPolicy) | ||
| { | ||
| case UnhandledExceptionPolicy.StopNode: | ||
| throw; | ||
| case UnhandledExceptionPolicy.StopPlugin: | ||
| //Stop plugin on exception | ||
| plugin.IsStopped = true; | ||
| break; | ||
| case UnhandledExceptionPolicy.Ignore: | ||
| // Log the exception and continue with the next handler | ||
| break; | ||
| default: | ||
| throw new InvalidCastException( | ||
| $"The exception policy {plugin.ExceptionPolicy} is not valid."); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Gets a <see cref="Akka.Actor.Props"/> object used for creating the <see cref="Blockchain"/> actor. | ||
| /// </summary> | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // Copyright (C) 2015-2024 The Neo Project. | ||
| // | ||
| // PluginSettings.cs file belongs to the neo project and is free | ||
| // software distributed under the MIT software license, see the | ||
| // accompanying file LICENSE in the main directory of the | ||
| // repository or http://www.opensource.org/licenses/mit-license.php | ||
| // for more details. | ||
| // | ||
| // Redistribution and use in source and binary forms with or without | ||
| // modifications are permitted. | ||
|  | ||
| using Microsoft.Extensions.Configuration; | ||
| using Org.BouncyCastle.Security; | ||
| using System; | ||
|  | ||
| namespace Neo.Plugins; | ||
|  | ||
| public abstract class PluginSettings(IConfigurationSection section) | ||
| { | ||
| public UnhandledExceptionPolicy ExceptionPolicy | ||
| { | ||
| get | ||
| { | ||
| var policyString = section.GetValue(nameof(UnhandledExceptionPolicy), nameof(UnhandledExceptionPolicy.StopNode)); | ||
| if (Enum.TryParse(policyString, true, out UnhandledExceptionPolicy policy)) | ||
| { | ||
| return policy; | ||
| } | ||
|  | ||
| throw new InvalidParameterException($"{policyString} is not a valid UnhandledExceptionPolicy"); | ||
| } | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // Copyright (C) 2015-2024 The Neo Project. | ||
| // | ||
| // UnhandledExceptionPolicy.cs file belongs to the neo project and is free | ||
| // software distributed under the MIT software license, see the | ||
| // accompanying file LICENSE in the main directory of the | ||
| // repository or http://www.opensource.org/licenses/mit-license.php | ||
| // for more details. | ||
| // | ||
| // Redistribution and use in source and binary forms with or without | ||
| // modifications are permitted. | ||
|  | ||
| namespace Neo.Plugins | ||
| { | ||
| public enum UnhandledExceptionPolicy : byte | ||
| { | ||
| Ignore = 0, | ||
| StopPlugin = 1, | ||
| StopNode = 2, | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -3,7 +3,8 @@ | |
| "Path": "ApplicationLogs_{0}", | ||
| "Network": 860833102, | ||
| "MaxStackSize": 65535, | ||
| "Debug": false | ||
| "Debug": false, | ||
| "UnhandledExceptionPolicy": "StopPlugin" | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better in almost all of them  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nothoing was changed since the last review but the deledage invoke. Different plugin has different behavior on unhandled exception that are precisely set by superboy. Default behavior means nothing here. | ||
| }, | ||
| "Dependency": [ | ||
| "RpcServer" | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| { | ||
| "PluginConfiguration": { | ||
| "UnhandledExceptionPolicy": "Ignore", | ||
| "Servers": [ | ||
| { | ||
| "Network": 860833102, | ||
|  | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What we have this requirement added?