diff --git a/src/Nethermind/Nethermind.Api/Extensions/IPlugin.cs b/src/Nethermind/Nethermind.Api/Extensions/IPlugin.cs
index 09a872ad8af..387a483504d 100644
--- a/src/Nethermind/Nethermind.Api/Extensions/IPlugin.cs
+++ b/src/Nethermind/Nethermind.Api/Extensions/IPlugin.cs
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using System;
using System.Threading.Tasks;
@@ -33,5 +33,7 @@ public interface INethermindPlugin : IAsyncDisposable
Task InitNetworkProtocol();
Task InitRpcModules();
+
+ bool MustInitialize { get => false; }
}
}
diff --git a/src/Nethermind/Nethermind.Config/ExitCodes.cs b/src/Nethermind/Nethermind.Config/ExitCodes.cs
index 1e90f871703..9d126ba1784 100644
--- a/src/Nethermind/Nethermind.Config/ExitCodes.cs
+++ b/src/Nethermind/Nethermind.Config/ExitCodes.cs
@@ -19,6 +19,9 @@ namespace Nethermind.Config;
public static class ExitCodes
{
+ public const int Ok = 0;
+ public const int GeneralError = 1;
+
// config errors 100...199
public const int NoEngineModule = 100;
diff --git a/src/Nethermind/Nethermind.Core/Exceptions/IExceptionWithExitCode.cs b/src/Nethermind/Nethermind.Core/Exceptions/IExceptionWithExitCode.cs
new file mode 100644
index 00000000000..550483fd37d
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Exceptions/IExceptionWithExitCode.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2021 Demerzel Solutions Limited
+// This file is part of the Nethermind library.
+//
+// The Nethermind library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Nethermind library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Nethermind. If not, see .
+//
+
+namespace Nethermind.Core.Exceptions;
+
+public interface IExceptionWithExitCode
+{
+ int ExitCode { get; }
+}
diff --git a/src/Nethermind/Nethermind.Core/Exceptions/InvalidConfigurationException.cs b/src/Nethermind/Nethermind.Core/Exceptions/InvalidConfigurationException.cs
new file mode 100644
index 00000000000..a83931fd3ea
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Exceptions/InvalidConfigurationException.cs
@@ -0,0 +1,30 @@
+// Copyright (c) 2021 Demerzel Solutions Limited
+// This file is part of the Nethermind library.
+//
+// The Nethermind library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Nethermind library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Nethermind. If not, see .
+//
+
+using System;
+
+namespace Nethermind.Core.Exceptions;
+
+public class InvalidConfigurationException: Exception, IExceptionWithExitCode
+{
+ public InvalidConfigurationException(string message, int exitCode): base(message)
+ {
+ ExitCode = exitCode;
+ }
+
+ public int ExitCode { get; }
+}
diff --git a/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs b/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs
index 10b420cf776..e1f6e64f817 100644
--- a/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -135,40 +135,13 @@ private void RunOneRoundOfInitialization(CancellationToken cancellationToken)
if (_logger.IsDebug) _logger.Debug($"Executing step: {stepInfo}");
- Stopwatch stopwatch = Stopwatch.StartNew();
stepInfo.Stage = StepInitializationStage.Executing;
- Task task = step.Execute(cancellationToken);
startedThisRound++;
- Task continuationTask = task.ContinueWith(t =>
- {
- stopwatch.Stop();
-
- if (t.IsFaulted && step.MustInitialize)
- {
- if (_logger.IsError) _logger.Error(
- $"Step {step.GetType().Name.PadRight(24)} failed after {stopwatch.ElapsedMilliseconds}ms",
- t.Exception);
- }
- else if (t.IsFaulted)
- {
- if (_logger.IsWarn) _logger.Warn(
- $"Step {step.GetType().Name.PadRight(24)} failed after {stopwatch.ElapsedMilliseconds}ms");
- }
- else
- {
- if (_logger.IsDebug) _logger.Debug(
- $"Step {step.GetType().Name.PadRight(24)} executed in {stopwatch.ElapsedMilliseconds}ms");
- }
-
- stepInfo.Stage = StepInitializationStage.Complete;
- _autoResetEvent.Set();
-
- if (_logger.IsDebug) _logger.Debug($"{step.GetType().Name.PadRight(24)} complete");
- });
+ Task task = ExecuteStep(step, stepInfo, cancellationToken);
if (step.MustInitialize)
{
- _allPending.Enqueue(continuationTask);
+ _allPending.Enqueue(task);
}
else
{
@@ -186,6 +159,46 @@ private void RunOneRoundOfInitialization(CancellationToken cancellationToken)
}
}
+ private async Task ExecuteStep(IStep step, StepInfo stepInfo, CancellationToken cancellationToken)
+ {
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ try
+ {
+ await step.Execute(cancellationToken);
+
+ if (_logger.IsDebug)
+ _logger.Debug(
+ $"Step {step.GetType().Name.PadRight(24)} executed in {stopwatch.ElapsedMilliseconds}ms");
+ }
+ catch (Exception exception)
+ {
+ if (step.MustInitialize)
+ {
+ if (_logger.IsError)
+ _logger.Error(
+ $"Step {step.GetType().Name.PadRight(24)} failed after {stopwatch.ElapsedMilliseconds}ms",
+ exception);
+
+ throw;
+ }
+
+ if (_logger.IsWarn)
+ {
+ _logger.Warn(
+ $"Step {step.GetType().Name.PadRight(24)} failed after {stopwatch.ElapsedMilliseconds}ms {exception}");
+ }
+ }
+ finally
+ {
+ stopwatch.Stop();
+
+ stepInfo.Stage = StepInitializationStage.Complete;
+ _autoResetEvent.Set();
+
+ if (_logger.IsDebug) _logger.Debug($"{step.GetType().Name.PadRight(24)} complete");
+ }
+ }
+
private IStep? CreateStepInstance(StepInfo stepInfo)
{
IStep? step = null;
diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeNodeStats.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeNodeStats.cs
index 5e4f1be6fda..28a93406b73 100644
--- a/src/Nethermind/Nethermind.Init/Steps/InitializeNodeStats.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/InitializeNodeStats.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -43,5 +43,7 @@ public Task Execute(CancellationToken _)
return Task.CompletedTask;
}
+
+ public bool MustInitialize => false;
}
}
diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializePlugins.cs b/src/Nethermind/Nethermind.Init/Steps/InitializePlugins.cs
index 82ac1ed05c1..10ae39152fe 100644
--- a/src/Nethermind/Nethermind.Init/Steps/InitializePlugins.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/InitializePlugins.cs
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using System;
using System.Diagnostics;
@@ -53,6 +53,7 @@ public async Task Execute(CancellationToken cancellationToken)
catch (Exception e)
{
if (logger.IsError) logger.Error($"Failed to initialize plugin {plugin.Name} by {plugin.Author}", e);
+ if (plugin.MustInitialize) throw;
}
}
}
diff --git a/src/Nethermind/Nethermind.Init/Steps/StartLogProducer.cs b/src/Nethermind/Nethermind.Init/Steps/StartLogProducer.cs
index df90e010f82..870f7811cc0 100644
--- a/src/Nethermind/Nethermind.Init/Steps/StartLogProducer.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/StartLogProducer.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -38,5 +38,7 @@ public Task Execute(CancellationToken cancellationToken)
_api.Publishers.Add(logPublisher);
return Task.CompletedTask;
}
+
+ public bool MustInitialize => false;
}
}
diff --git a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
index 43274a55a7c..d92e65f8f0c 100644
--- a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using System;
using System.Collections.Generic;
@@ -74,4 +74,6 @@ await _api.MonitoringService.StartAsync().ContinueWith(x =>
logger.Info("Grafana / Prometheus metrics are disabled in configuration");
}
}
+
+ public bool MustInitialize => false;
}
diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs
index a09a2a7b5df..c2df6bfa3e0 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs
@@ -26,6 +26,7 @@
using Nethermind.Consensus.Clique;
using Nethermind.Consensus.Producers;
using Nethermind.Core;
+using Nethermind.Core.Exceptions;
using Nethermind.Core.Test.Builders;
using Nethermind.Db;
using Nethermind.JsonRpc;
@@ -80,7 +81,7 @@ public void Setup()
Epoch = CliqueConfig.Default.Epoch,
Period = CliqueConfig.Default.BlockPeriod
};
- _plugin = new MergePlugin(new EnvironmentExitMock());
+ _plugin = new MergePlugin();
_consensusPlugin = new();
}
@@ -140,7 +141,7 @@ public async Task InitThrowsWhenNoEngineApiUrlsConfigured(bool jsonRpcEnabled, b
await _plugin.Invoking((plugin) => plugin.Init(_context))
.Should()
- .ThrowAsync();
+ .ThrowAsync();
}
[Test]
@@ -187,25 +188,7 @@ public async Task InitThrowExceptionIfBodiesAndReceiptIsDisabled(bool downloadBo
}
else
{
- await invocation.Should().ThrowAsync();
- }
- }
-
- private class EnvironmentExitMock : IEnvironment
- {
- public string GetEnvironmentVariable(string variableName)
- {
- throw new NotImplementedException();
- }
-
- public IDictionary GetEnvironmentVariables()
- {
- throw new NotImplementedException();
- }
-
- public void Exit(int exitCode)
- {
- throw new InvalidOperationException($"Exit with exitCode: {exitCode}");
+ await invocation.Should().ThrowAsync();
}
}
}
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
index 85d3476376b..73d1302101f 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
@@ -29,6 +29,7 @@
using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Crypto;
+using Nethermind.Core.Exceptions;
using Nethermind.Db;
using Nethermind.Facade.Proxy;
using Nethermind.JsonRpc;
@@ -67,16 +68,8 @@ public partial class MergePlugin : IConsensusWrapperPlugin, ISynchronizationPlug
public virtual bool MergeEnabled => _mergeConfig.Enabled;
- private readonly IEnvironment _environment = new EnvironmentWrapper();
-
public MergePlugin() { }
- public MergePlugin(IEnvironment? environment = null)
- {
- if (environment != null)
- _environment = environment;
- }
-
public virtual Task Init(INethermindApi nethermindApi)
{
_api = nethermindApi;
@@ -167,8 +160,9 @@ private void EnsureReceiptAvailable()
{
if (!syncConfig.DownloadReceiptsInFastSync || !syncConfig.DownloadBodiesInFastSync)
{
- if (_logger.IsError) _logger.Error("Receipt and body must be available for merge to function. The following configs values should be set to true: Sync.DownloadReceiptsInFastSync, Sync.DownloadBodiesInFastSync");
- _environment.Exit(ExitCodes.NoDownloadOldReceiptsOrBlocks);
+ throw new InvalidConfigurationException(
+ "Receipt and body must be available for merge to function. The following configs values should be set to true: Sync.DownloadReceiptsInFastSync, Sync.DownloadBodiesInFastSync",
+ ExitCodes.NoDownloadOldReceiptsOrBlocks);
}
}
}
@@ -210,8 +204,9 @@ private void EnsureEngineModuleIsConfigured()
if (!hasEngineApiConfigured)
{
- if (_logger.IsError) _logger.Error("Engine module wasn't configured on any port. Nethermind can't work without engine port configured. Verify your RPC configuration. You can find examples in our docs: https://docs.nethermind.io/nethermind/ethereum-client/engine-jsonrpc-configuration-examples");
- _environment.Exit(ExitCodes.NoEngineModule);
+ throw new InvalidConfigurationException(
+ "Engine module wasn't configured on any port. Nethermind can't work without engine port configured. Verify your RPC configuration. You can find examples in our docs: https://docs.nethermind.io/nethermind/ethereum-client/engine-jsonrpc-configuration-examples",
+ ExitCodes.NoEngineModule);
}
}
@@ -453,5 +448,7 @@ public Task InitSynchronization()
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
public string SealEngineType => "Eth2Merge";
+
+ public bool MustInitialize { get => true; }
}
}
diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs
index 1136919e68f..afdb7128cce 100644
--- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs
+++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs
@@ -1,22 +1,23 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
using System.Threading;
using System.Threading.Tasks;
+using FluentAssertions;
using FluentAssertions.Execution;
using Nethermind.Api;
using Nethermind.Config;
@@ -26,6 +27,7 @@
using Nethermind.Runner.Ethereum.Api;
using Nethermind.Runner.Ethereum.Steps;
using Nethermind.Serialization.Json;
+using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
namespace Nethermind.Runner.Test.Ethereum.Steps
@@ -85,7 +87,7 @@ public async Task With_steps_from_here_AuRa()
runnerContext,
LimboLogs.Instance);
- using CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromSeconds(1));
+ using CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromSeconds(2));
try
{
@@ -93,10 +95,7 @@ public async Task With_steps_from_here_AuRa()
}
catch (Exception e)
{
- if (!(e is OperationCanceledException))
- {
- throw new AssertionFailedException($"Exception should be {nameof(OperationCanceledException)}");
- }
+ e.Should().BeOfType();
}
}
@@ -111,7 +110,7 @@ public async Task With_failing_steps()
runnerContext,
LimboLogs.Instance);
- using CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromSeconds(1));
+ using CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromSeconds(2));
try
{
@@ -211,7 +210,7 @@ public StepCAuRa(AuRaNethermindApi runnerContext)
public override async Task Execute(CancellationToken cancellationToken)
{
- await Task.Run(() => throw new Exception());
+ await Task.Run(() => throw new TestException());
}
}
@@ -221,4 +220,8 @@ public StepCStandard(NethermindApi runnerContext)
{
}
}
+
+ class TestException : Exception
+ {
+ }
}
diff --git a/src/Nethermind/Nethermind.Runner/Program.cs b/src/Nethermind/Nethermind.Runner/Program.cs
index 16c8bf7d82f..8f543ae8470 100644
--- a/src/Nethermind/Nethermind.Runner/Program.cs
+++ b/src/Nethermind/Nethermind.Runner/Program.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -34,6 +34,7 @@
using Nethermind.Consensus.Clique;
using Nethermind.Consensus.Ethash;
using Nethermind.Core;
+using Nethermind.Core.Exceptions;
using Nethermind.Db.Rocks;
using Nethermind.Hive;
using Nethermind.KeyStore.Config;
@@ -147,7 +148,6 @@ private static void Run(string[] args)
app.OnExecute(async () =>
{
- _appClosed.Reset();
IConfigProvider configProvider = BuildConfigProvider(app, loggerConfigSource, logLevelOverride, configsDirectory, configFile);
IInitConfig initConfig = configProvider.GetConfig();
IKeyStoreConfig keyStoreConfig = configProvider.GetConfig();
@@ -192,25 +192,57 @@ private static void Run(string[] args)
INethermindApi nethermindApi = apiBuilder.Create(plugins.OfType());
((List)nethermindApi.Plugins).AddRange(plugins);
+ _appClosed.Reset();
EthereumRunner ethereumRunner = new(nethermindApi);
- await ethereumRunner.Start(_processCloseCancellationSource.Token).ContinueWith(x =>
+ int exitCode = ExitCodes.Ok;
+ try
{
- if (x.IsFaulted && _logger.IsError)
- _logger.Error("Error during ethereum runner start", x.Exception);
- });
+ await ethereumRunner.Start(_processCloseCancellationSource.Token);
- _ = await Task.WhenAny(_cancelKeySource.Task, _processExit.Task);
+ _ = await Task.WhenAny(_cancelKeySource.Task, _processExit.Task);
+ }
+ catch (Exception e)
+ {
+ if (_logger.IsError) _logger.Error("Error during ethereum runner start", e);
+ if (e is IExceptionWithExitCode withExit)
+ {
+ exitCode = withExit.ExitCode;
+ }
+ else
+ {
+ exitCode = ExitCodes.GeneralError;
+ }
+ _processCloseCancellationSource.Cancel();
+ }
_logger.Info("Closing, please wait until all functions are stopped properly...");
await ethereumRunner.StopAsync();
_logger.Info("All done, goodbye!");
_appClosed.Set();
- return 0;
+ return exitCode;
});
- _ = app.Execute(args);
- _appClosed.Wait();
+ try
+ {
+ Environment.ExitCode = app.Execute(args);
+ }
+ catch (Exception e)
+ {
+ if (e is IExceptionWithExitCode withExit)
+ {
+ Environment.ExitCode = withExit.ExitCode;
+ }
+ else
+ {
+ Environment.ExitCode = ExitCodes.GeneralError;
+ }
+ throw;
+ }
+ finally
+ {
+ _appClosed.Wait();
+ }
}
private static IntPtr OnResolvingUnmanagedDll(Assembly _, string nativeLibraryName)
diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg
index 17a9a7b899b..2b4256ae876 100644
--- a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg
+++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg
@@ -38,4 +38,4 @@
"Merge": {
"Enabled": true
}
-}
\ No newline at end of file
+}