Set ReasonableCoreShutdownTimeout = 30s and a few minor changes.
MODIFY
WalletWasabi/BitcoinCore/Processes/BitcoindRpcProcessBridge.cs
WalletWasabi/BitcoinCore/Processes/BitcoindRpcProcessBridge.cs
@@ -20,7 +20,7 @@ namespace WalletWasabi.BitcoinCore.Processes
public const string PidFileName = "bitcoin.pid";
/// <summary>Experimentally found constant.</summary>
- private readonly TimeSpan ReasonableCoreShutdownTimeout = TimeSpan.FromSeconds(21);
+ private readonly TimeSpan ReasonableCoreShutdownTimeout = TimeSpan.FromSeconds(30);
public BitcoindRpcProcessBridge(IRPCClient rpcClient, string dataDir, bool printToConsole)
{
@@ -34,7 +34,7 @@ namespace WalletWasabi.BitcoinCore.Processes
}
public Network Network { get; }
- public IRPCClient RpcClient { get; set; }
+ public IRPCClient RpcClient { get; }
public string DataDir { get; }
public bool PrintToConsole { get; }
public PidFile PidFile { get; }
@@ -126,7 +126,8 @@ namespace WalletWasabi.BitcoinCore.Processes
return;
}
- ProcessAsync process = Process; // process is guaranteed to be non-null at this point.
+ // "process" variable is guaranteed to be non-null at this point.
+ ProcessAsync process = Process;
using var cts = new CancellationTokenSource(ReasonableCoreShutdownTimeout);
int? pid = await PidFile.TryReadAsync().ConfigureAwait(false);
@@ -138,19 +139,28 @@ namespace WalletWasabi.BitcoinCore.Processes
try
{
+ bool isKilled = false;
+
try
{
+ // Stop Bitcoin daemon using RPC "stop" command.
+ // The command actually only initiates the bitcoind graceful shutdown procedure.
+ // Our time budget for the bitcoind to stop is given by "ReasonableCoreShutdownTimeout".
await RpcClient.StopAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.LogWarning(ex);
process.Kill();
+ isKilled = true;
}
+ if (!isKilled)
+ {
Logger.LogDebug($"Wait until the process is stopped.");
await process.WaitForExitAsync(cts.Token).ConfigureAwait(false);
}
+ }
finally
{
Logger.LogDebug($"Wait until the process is stopped.");

MODIFY
WalletWasabi/Microservices/ProcessAsync.cs
WalletWasabi/Microservices/ProcessAsync.cs
@@ -97,6 +97,7 @@ namespace WalletWasabi.Microservices
{
if (Process.HasExited)
{
+ Logger.LogTrace("Process has already exited.");
return;
}
@@ -105,17 +106,24 @@ namespace WalletWasabi.Microservices
// If this token is already in the canceled state, the delegate will be run immediately and synchronously.
using (cancel.Register(() => ProcessExecutionTcs.TrySetCanceled()))
{
- await ProcessExecutionTcs.Task;
+ Logger.LogTrace("Wait for the process to exit.");
+
+ await ProcessExecutionTcs.Task.ConfigureAwait(false);
+
+ Logger.LogTrace("Process has exited.");
}
}
catch (OperationCanceledException ex)
{
+ Logger.LogTrace("User canceled waiting for process exit.");
+
if (killOnCancel)
{
if (!Process.HasExited)
{
try
{
+ Logger.LogTrace("Kill process.");
Process.Kill(entireProcessTree: true);
}
catch (Exception e)

Set ReasonableCoreShutdownTimeout = 30s and a few minor changes.