Add sync Dispose function
MODIFY
WalletWasabi.Fluent.Desktop/Program.cs
WalletWasabi.Fluent.Desktop/Program.cs
@@ -55,14 +55,13 @@ public class Program
}
Exception? exceptionToReport = null;
- SingleInstanceChecker? singleInstanceChecker = null;
if (runGui)
{
try
{
var (uiConfig, config) = LoadOrCreateConfigs(dataDir);
- singleInstanceChecker = new SingleInstanceChecker(config.Network);
+ using SingleInstanceChecker singleInstanceChecker = new(config.Network);
singleInstanceChecker.EnsureSingleOrThrowAsync().GetAwaiter().GetResult();
Global = CreateGlobal(dataDir, uiConfig, config);
@@ -89,14 +88,8 @@ public class Program
}
// Start termination/disposal of the application.
-
TerminateService.Terminate();
- if (singleInstanceChecker is { } single)
- {
- Task.Run(async () => await single.DisposeAsync()).Wait();
- }
-
if (exceptionToReport is { })
{
// Trigger the CrashReport process if required.

MODIFY
WalletWasabi/Services/SingleInstanceChecker.cs
WalletWasabi/Services/SingleInstanceChecker.cs
@@ -12,7 +12,7 @@ namespace WalletWasabi.Services;
public class SingleInstanceChecker : BackgroundService, IAsyncDisposable
{
- private const string WasabiMagicString = "InCryptoWeTrust";
+ private const string WasabiMagicString = "InBitcoinWeTrust";
public static readonly TimeSpan ClientTimeOut = TimeSpan.FromSeconds(2);
/// <summary>
@@ -86,10 +86,12 @@ public class SingleInstanceChecker : BackgroundService, IAsyncDisposable
await client.ConnectAsync(IPAddress.Loopback, Port, cts.Token).ConfigureAwait(false);
+#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task
await using NetworkStream networkStream = client.GetStream();
-
networkStream.WriteTimeout = (int)ClientTimeOut.TotalMilliseconds * 2;
await using var writer = new StreamWriter(networkStream, Encoding.UTF8);
+#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task
+
await writer.WriteAsync(new StringBuilder(WasabiMagicString), cts.Token).ConfigureAwait(false);
await writer.FlushAsync().ConfigureAwait(false);
await networkStream.FlushAsync(cts.Token).ConfigureAwait(false);
@@ -141,7 +143,10 @@ public class SingleInstanceChecker : BackgroundService, IAsyncDisposable
client.ReceiveBufferSize = 1000;
try
{
+#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task
await using NetworkStream networkStream = client.GetStream();
+#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task
+
networkStream.ReadTimeout = (int)ClientTimeOut.TotalMilliseconds;
using var reader = new StreamReader(networkStream, Encoding.UTF8);
// Make sure the client will be disconnected.
@@ -183,4 +188,26 @@ public class SingleInstanceChecker : BackgroundService, IAsyncDisposable
DisposeCts.Dispose();
}
+
+ public override void Dispose()
+ {
+ base.Dispose();
+
+ // This is added because Dispose called from the Main and Main cannot be an async function.
+ DisposeCts.Cancel();
+
+ // Stopping the execution task and wait until it finishes.
+ using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(20));
+ while (!ExecuteTask.IsCompleted && !timeout.IsCancellationRequested)
+ {
+ Thread.Sleep(10);
+ if (timeout.IsCancellationRequested)
+ {
+ Logger.LogWarning($"{nameof(SingleInstanceChecker)} cannot be disposed properly in time.");
+ break;
+ }
+ }
+
+ DisposeCts.Dispose();
+ }
}

Add sync Dispose function