Skip to content

Commit 2bbf197

Browse files
committed
Add extra synchronization to IPC state management
Thanks @ezhevita
1 parent 5d26652 commit 2bbf197

File tree

2 files changed

+67
-25
lines changed

2 files changed

+67
-25
lines changed

ArchiSteamFarm/Core/ASF.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,8 @@ private static async Task OnChangedConfigFile(string name) {
355355
}
356356

357357
ArchiLogger.LogGenericInfo(Strings.IPCConfigChanged);
358-
await ArchiKestrel.Stop().ConfigureAwait(false);
359-
await ArchiKestrel.Start().ConfigureAwait(false);
358+
359+
await ArchiKestrel.Restart().ConfigureAwait(false);
360360
}
361361

362362
private static async Task OnChangedFile(string name, string fullPath) {

ArchiSteamFarm/IPC/ArchiKestrel.cs

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
using System.Reflection;
3131
using System.Text.Json;
3232
using System.Text.Json.Nodes;
33+
using System.Threading;
3334
using System.Threading.Tasks;
3435
using ArchiSteamFarm.Core;
3536
using ArchiSteamFarm.Helpers.Json;
@@ -64,6 +65,8 @@ internal static class ArchiKestrel {
6465

6566
internal static HistoryTarget? HistoryTarget { get; private set; }
6667

68+
private static readonly SemaphoreSlim StateSemaphore = new(1, 1);
69+
6770
private static WebApplication? WebApplication;
6871

6972
internal static void OnNewHistoryTarget(HistoryTarget? historyTarget = null) {
@@ -78,43 +81,43 @@ internal static void OnNewHistoryTarget(HistoryTarget? historyTarget = null) {
7881
}
7982
}
8083

81-
internal static async Task Start() {
82-
if (WebApplication != null) {
83-
return;
84-
}
85-
86-
ASF.ArchiLogger.LogGenericInfo(Strings.IPCStarting);
87-
88-
// Init history logger for /Api/Log usage
89-
Logging.InitHistoryLogger();
90-
91-
WebApplication webApplication = await CreateWebApplication().ConfigureAwait(false);
84+
internal static async Task Restart() {
85+
await StateSemaphore.WaitAsync().ConfigureAwait(false);
9286

9387
try {
94-
// Start the server
95-
await webApplication.StartAsync().ConfigureAwait(false);
96-
} catch (Exception e) {
97-
ASF.ArchiLogger.LogGenericException(e);
98-
99-
await webApplication.DisposeAsync().ConfigureAwait(false);
88+
await StopInternally().ConfigureAwait(false);
89+
await StartInternally().ConfigureAwait(false);
90+
} finally {
91+
StateSemaphore.Release();
92+
}
93+
}
10094

95+
internal static async Task Start() {
96+
if (IsRunning) {
10197
return;
10298
}
10399

104-
WebApplication = webApplication;
100+
await StateSemaphore.WaitAsync().ConfigureAwait(false);
105101

106-
ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady);
102+
try {
103+
await StartInternally().ConfigureAwait(false);
104+
} finally {
105+
StateSemaphore.Release();
106+
}
107107
}
108108

109109
internal static async Task Stop() {
110-
if (WebApplication == null) {
110+
if (!IsRunning) {
111111
return;
112112
}
113113

114-
await WebApplication.StopAsync().ConfigureAwait(false);
115-
await WebApplication.DisposeAsync().ConfigureAwait(false);
114+
await StateSemaphore.WaitAsync().ConfigureAwait(false);
116115

117-
WebApplication = null;
116+
try {
117+
await StopInternally().ConfigureAwait(false);
118+
} finally {
119+
StateSemaphore.Release();
120+
}
118121
}
119122

120123
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "PathString is a primitive, it's unlikely to be trimmed to the best of our knowledge")]
@@ -519,4 +522,43 @@ private static void OnPrepareResponse(StaticFileResponseContext context) {
519522

520523
headers.CacheControl = cacheControl;
521524
}
525+
526+
private static async Task StartInternally() {
527+
if (WebApplication != null) {
528+
return;
529+
}
530+
531+
ASF.ArchiLogger.LogGenericInfo(Strings.IPCStarting);
532+
533+
// Init history logger for /Api/Log usage
534+
Logging.InitHistoryLogger();
535+
536+
WebApplication webApplication = await CreateWebApplication().ConfigureAwait(false);
537+
538+
try {
539+
// Start the server
540+
await webApplication.StartAsync().ConfigureAwait(false);
541+
} catch (Exception e) {
542+
ASF.ArchiLogger.LogGenericException(e);
543+
544+
await webApplication.DisposeAsync().ConfigureAwait(false);
545+
546+
return;
547+
}
548+
549+
WebApplication = webApplication;
550+
551+
ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady);
552+
}
553+
554+
private static async Task StopInternally() {
555+
if (WebApplication == null) {
556+
return;
557+
}
558+
559+
await WebApplication.StopAsync().ConfigureAwait(false);
560+
await WebApplication.DisposeAsync().ConfigureAwait(false);
561+
562+
WebApplication = null;
563+
}
522564
}

0 commit comments

Comments
 (0)