mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 16:39:21 +01:00
Address new stylecop warnings
This commit is contained in:
@@ -237,7 +237,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
if (!enumerable.Any())
|
||||
{
|
||||
ulong newId;
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
newId = channelIdCounter++;
|
||||
logger.LogTrace(
|
||||
"Mapping private channel {0}:{1} as {2}",
|
||||
@@ -268,7 +268,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
|
||||
var splits = new List<string>(message.Content.Trim().Split(' '));
|
||||
var address = splits[0];
|
||||
if (address.Length > 1 && (address[address.Length - 1] == ':' || address[address.Length - 1] == ','))
|
||||
if (address.Length > 1 && (address.Last() == ':' || address.Last() == ','))
|
||||
address = address[0..^1];
|
||||
|
||||
address = address.ToUpperInvariant();
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
|
||||
var enumerator = channels.Select(x => GetModelChannelFromDBChannel(x)).Where(x => x != null).ToList();
|
||||
|
||||
lock (this)
|
||||
lock (client)
|
||||
{
|
||||
mappedChannels.Clear();
|
||||
mappedChannels.AddRange(enumerator.Select(x => x.RealId));
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
}
|
||||
|
||||
ulong userId, channelId;
|
||||
lock (this)
|
||||
lock (client)
|
||||
{
|
||||
userId = MapAndGetChannelId(queryChannelIdMap);
|
||||
channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
|
||||
@@ -250,7 +250,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
public override Task<bool> Connect(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
{
|
||||
disconnecting = false;
|
||||
lock (this)
|
||||
lock (client)
|
||||
try
|
||||
{
|
||||
client.Connect(address, port);
|
||||
@@ -384,7 +384,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
{
|
||||
if (channels.Any(x => x.IrcChannel == null))
|
||||
throw new InvalidOperationException("ChatChannel missing IrcChannel!");
|
||||
lock (this)
|
||||
lock (client)
|
||||
{
|
||||
var channelsWithKeys = new Dictionary<string, string>();
|
||||
var hs = new HashSet<string>(); // for unique inserts
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
return newerDmbTcs.Task;
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
|
||||
{
|
||||
jobLockCounts.Remove(job.Id);
|
||||
@@ -137,7 +137,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
|
||||
if (newProvider == null)
|
||||
return;
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
{
|
||||
nextDmbProvider?.Dispose();
|
||||
nextDmbProvider = newProvider;
|
||||
@@ -153,7 +153,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
throw new InvalidOperationException("No .dmb available!");
|
||||
if (lockCount < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
{
|
||||
var jobId = nextDmbProvider.CompileJob.Id;
|
||||
var incremented = jobLockCounts[jobId] += lockCount;
|
||||
@@ -221,7 +221,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
return null; // omae wa mou shinderu
|
||||
}
|
||||
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
{
|
||||
if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
|
||||
{
|
||||
@@ -252,7 +252,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
List<long> jobIdsToSkip;
|
||||
|
||||
// don't clean locked directories
|
||||
lock (this)
|
||||
lock (jobLockCounts)
|
||||
jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
|
||||
|
||||
List<string> jobUidsToNotErase = null;
|
||||
|
||||
@@ -86,6 +86,11 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
/// </summary>
|
||||
readonly ILogger<DreamMaker> logger;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for <see cref="compiling"/>.
|
||||
/// </summary>
|
||||
readonly object compilingLock;
|
||||
|
||||
/// <summary>
|
||||
/// If a compile job is running
|
||||
/// </summary>
|
||||
@@ -123,6 +128,8 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
|
||||
this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
compilingLock = new object();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -175,50 +182,48 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
job.MinimumSecurityLevel = securityLevel; // needed for the TempDmbProvider
|
||||
var timeoutAt = DateTimeOffset.Now.AddSeconds(timeout);
|
||||
|
||||
using (var provider = new TemporaryDmbProvider(ioManager.ResolvePath(dirA), String.Concat(job.DmeName, DmbExtension), job))
|
||||
using (var controller = await sessionControllerFactory.LaunchNew(provider, byondLock, launchParameters, true, true, true, cancellationToken).ConfigureAwait(false))
|
||||
using var provider = new TemporaryDmbProvider(ioManager.ResolvePath(dirA), String.Concat(job.DmeName, DmbExtension), job);
|
||||
using var controller = await sessionControllerFactory.LaunchNew(provider, byondLock, launchParameters, true, true, true, cancellationToken).ConfigureAwait(false);
|
||||
var launchResult = await controller.LaunchResult.ConfigureAwait(false);
|
||||
|
||||
var now = DateTimeOffset.Now;
|
||||
if (now < timeoutAt && launchResult.StartupTime.HasValue)
|
||||
{
|
||||
var launchResult = await controller.LaunchResult.ConfigureAwait(false);
|
||||
var timeoutTask = Task.Delay(timeoutAt - now, cancellationToken);
|
||||
|
||||
var now = DateTimeOffset.Now;
|
||||
if (now < timeoutAt && launchResult.StartupTime.HasValue)
|
||||
{
|
||||
var timeoutTask = Task.Delay(timeoutAt - now, cancellationToken);
|
||||
|
||||
await Task.WhenAny(controller.Lifetime, timeoutTask).ConfigureAwait(false);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
if (controller.Lifetime.IsCompleted)
|
||||
{
|
||||
var validationStatus = controller.ApiValidationStatus;
|
||||
logger.LogTrace("API validation status: {0}", validationStatus);
|
||||
|
||||
job.DMApiVersion = controller.DMApiVersion;
|
||||
switch (validationStatus)
|
||||
{
|
||||
case ApiValidationStatus.RequiresUltrasafe:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Ultrasafe;
|
||||
return;
|
||||
case ApiValidationStatus.RequiresSafe:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Safe;
|
||||
return;
|
||||
case ApiValidationStatus.RequiresTrusted:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Trusted;
|
||||
return;
|
||||
case ApiValidationStatus.NeverValidated:
|
||||
throw new JobException(ErrorCode.DreamMakerNeverValidated);
|
||||
case ApiValidationStatus.BadValidationRequest:
|
||||
throw new JobException(ErrorCode.DreamMakerInvalidValidation);
|
||||
case ApiValidationStatus.UnaskedValidationRequest:
|
||||
default:
|
||||
throw new InvalidOperationException(
|
||||
$"Session controller returned unexpected ApiValidationStatus: {validationStatus}");
|
||||
}
|
||||
}
|
||||
|
||||
throw new JobException(ErrorCode.DreamMakerValidationTimeout);
|
||||
await Task.WhenAny(controller.Lifetime, timeoutTask).ConfigureAwait(false);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
if (controller.Lifetime.IsCompleted)
|
||||
{
|
||||
var validationStatus = controller.ApiValidationStatus;
|
||||
logger.LogTrace("API validation status: {0}", validationStatus);
|
||||
|
||||
job.DMApiVersion = controller.DMApiVersion;
|
||||
switch (validationStatus)
|
||||
{
|
||||
case ApiValidationStatus.RequiresUltrasafe:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Ultrasafe;
|
||||
return;
|
||||
case ApiValidationStatus.RequiresSafe:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Safe;
|
||||
return;
|
||||
case ApiValidationStatus.RequiresTrusted:
|
||||
job.MinimumSecurityLevel = DreamDaemonSecurity.Trusted;
|
||||
return;
|
||||
case ApiValidationStatus.NeverValidated:
|
||||
throw new JobException(ErrorCode.DreamMakerNeverValidated);
|
||||
case ApiValidationStatus.BadValidationRequest:
|
||||
throw new JobException(ErrorCode.DreamMakerInvalidValidation);
|
||||
case ApiValidationStatus.UnaskedValidationRequest:
|
||||
default:
|
||||
throw new InvalidOperationException(
|
||||
$"Session controller returned unexpected ApiValidationStatus: {validationStatus}");
|
||||
}
|
||||
}
|
||||
|
||||
throw new JobException(ErrorCode.DreamMakerValidationTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,7 +235,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
async Task<int> RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var dm = processExecutor.LaunchProcess(
|
||||
using var dm = processExecutor.LaunchProcess(
|
||||
dreamMakerPath,
|
||||
ioManager.ResolvePath(
|
||||
ioManager.ConcatPath(
|
||||
@@ -238,18 +243,16 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
ADirectoryName)),
|
||||
$"-clean {job.DmeName}.{DmeExtension}",
|
||||
true,
|
||||
true))
|
||||
{
|
||||
int exitCode;
|
||||
using (cancellationToken.Register(() => dm.Terminate()))
|
||||
exitCode = await dm.Lifetime.ConfigureAwait(false);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
true);
|
||||
int exitCode;
|
||||
using (cancellationToken.Register(() => dm.Terminate()))
|
||||
exitCode = await dm.Lifetime.ConfigureAwait(false);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
logger.LogDebug("DreamMaker exit code: {0}", exitCode);
|
||||
job.Output = dm.GetCombinedOutput();
|
||||
logger.LogDebug("DreamMaker output: {0}{1}", Environment.NewLine, job.Output);
|
||||
return exitCode;
|
||||
}
|
||||
logger.LogDebug("DreamMaker exit code: {0}", exitCode);
|
||||
job.Output = dm.GetCombinedOutput();
|
||||
logger.LogDebug("DreamMaker output: {0}{1}", Environment.NewLine, job.Output);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -480,46 +483,42 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
|
||||
logger.LogTrace("Begin Compile");
|
||||
|
||||
lock (this)
|
||||
lock (compilingLock)
|
||||
{
|
||||
if (compiling)
|
||||
throw new JobException(ErrorCode.DreamMakerCompileJobInProgress);
|
||||
compiling = true;
|
||||
}
|
||||
|
||||
using (var progressCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
|
||||
using var progressCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
var progressTask = estimatedDuration.HasValue ? ProgressTask(progressReporter, estimatedDuration.Value, cancellationToken) : Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
var progressTask = estimatedDuration.HasValue ? ProgressTask(progressReporter, estimatedDuration.Value, cancellationToken) : Task.CompletedTask;
|
||||
try
|
||||
{
|
||||
using (var byondLock = await byond.UseExecutables(null, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
await SendDeploymentMessage(revisionInformation, byondLock, cancellationToken).ConfigureAwait(false);
|
||||
using var byondLock = await byond.UseExecutables(null, cancellationToken).ConfigureAwait(false);
|
||||
await SendDeploymentMessage(revisionInformation, byondLock, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var job = new Models.CompileJob
|
||||
{
|
||||
DirectoryName = Guid.NewGuid(),
|
||||
DmeName = dreamMakerSettings.ProjectName,
|
||||
RevisionInformation = revisionInformation,
|
||||
ByondVersion = byondLock.Version.ToString()
|
||||
};
|
||||
|
||||
await RunCompileJob(job, dreamMakerSettings, byondLock, repository, apiValidateTimeout, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return job;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
var job = new Models.CompileJob
|
||||
{
|
||||
await eventConsumer.HandleEvent(EventType.CompileCancelled, null, default).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
compiling = false;
|
||||
progressCts.Cancel();
|
||||
await progressTask.ConfigureAwait(false);
|
||||
}
|
||||
DirectoryName = Guid.NewGuid(),
|
||||
DmeName = dreamMakerSettings.ProjectName,
|
||||
RevisionInformation = revisionInformation,
|
||||
ByondVersion = byondLock.Version.ToString()
|
||||
};
|
||||
|
||||
await RunCompileJob(job, dreamMakerSettings, byondLock, repository, apiValidateTimeout, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return job;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
await eventConsumer.HandleEvent(EventType.CompileCancelled, null, default).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
compiling = false;
|
||||
progressCts.Cancel();
|
||||
await progressTask.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly Api.Models.Instance metadata;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for <see cref="timerCts"/> and <see cref="timerTask"/>.
|
||||
/// </summary>
|
||||
readonly object timerLock;
|
||||
|
||||
/// <summary>
|
||||
/// The auto update <see cref="Task"/>
|
||||
/// </summary>
|
||||
@@ -143,6 +148,8 @@ namespace Tgstation.Server.Host.Components
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
timerLock = new object();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -605,7 +612,7 @@ namespace Tgstation.Server.Host.Components
|
||||
public async Task SetAutoUpdateInterval(uint newInterval)
|
||||
{
|
||||
Task toWait;
|
||||
lock (this)
|
||||
lock (timerLock)
|
||||
{
|
||||
if (timerTask != null)
|
||||
{
|
||||
@@ -619,7 +626,7 @@ namespace Tgstation.Server.Host.Components
|
||||
await toWait.ConfigureAwait(false);
|
||||
if (newInterval == 0)
|
||||
return;
|
||||
lock (this)
|
||||
lock (timerLock)
|
||||
{
|
||||
// race condition, just quit
|
||||
if (timerTask != null)
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Tgstation.Server.Host.Components
|
||||
readonly ILogger<InstanceManager> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Map of <see cref="Api.Models.Instance.Id"/>s to respective <see cref="IInstance"/>s
|
||||
/// Map of <see cref="Api.Models.Instance.Id"/>s to respective <see cref="IInstance"/>s. Also used as a <see langword="lock"/> <see cref="object"/>.
|
||||
/// </summary>
|
||||
readonly IDictionary<long, IInstance> instances;
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
lock (instances)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
@@ -143,7 +143,7 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
if (metadata == null)
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
lock (this)
|
||||
lock (instances)
|
||||
{
|
||||
if (!instances.TryGetValue(metadata.Id, out IInstance instance))
|
||||
throw new InvalidOperationException("Instance not online!");
|
||||
@@ -180,7 +180,7 @@ namespace Tgstation.Server.Host.Components
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
logger.LogInformation("Offlining instance ID {0}", metadata.Id);
|
||||
IInstance instance;
|
||||
lock (this)
|
||||
lock (instances)
|
||||
{
|
||||
if (!instances.TryGetValue(metadata.Id, out instance))
|
||||
throw new InvalidOperationException("Instance not online!");
|
||||
@@ -223,7 +223,7 @@ namespace Tgstation.Server.Host.Components
|
||||
var instance = instanceFactory.CreateInstance(this, metadata);
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
lock (instances)
|
||||
{
|
||||
if (instances.ContainsKey(metadata.Id))
|
||||
throw new InvalidOperationException("Instance already online!");
|
||||
@@ -309,9 +309,9 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
private void CheckSystemCompatibility()
|
||||
{
|
||||
using (var systemIdentity = systemIdentityFactory.GetCurrent())
|
||||
if (!systemIdentity.CanCreateSymlinks)
|
||||
throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
|
||||
using var systemIdentity = systemIdentityFactory.GetCurrent();
|
||||
if (!systemIdentity.CanCreateSymlinks)
|
||||
throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
|
||||
readonly ILogger<Configuration> logger;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SemaphoreSlim"/> for <see cref="Configuration"/>
|
||||
/// The <see cref="SemaphoreSlim"/> for <see cref="Configuration"/>. Also used as a <see langword="lock"/> <see cref="object"/>.
|
||||
/// </summary>
|
||||
readonly SemaphoreSlim semaphore;
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
|
||||
if (!headFileExistsTask.Result && !tailFileExistsTask.Result)
|
||||
return null;
|
||||
|
||||
string IncludeLine(string filePath) => String.Format(CultureInfo.InvariantCulture, "#include \"{0}\"", filePath);
|
||||
static string IncludeLine(string filePath) => String.Format(CultureInfo.InvariantCulture, "#include \"{0}\"", filePath);
|
||||
|
||||
return new ServerSideModifications(headFileExistsTask.Result ? IncludeLine(CodeModificationsHeadFile) : null, tailFileExistsTask.Result ? IncludeLine(CodeModificationsTailFile) : null, false);
|
||||
}
|
||||
@@ -235,7 +235,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
|
||||
|
||||
void ReadImpl()
|
||||
{
|
||||
lock (this)
|
||||
lock (semaphore)
|
||||
try
|
||||
{
|
||||
var content = synchronousIOManager.ReadFile(path);
|
||||
@@ -366,7 +366,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
|
||||
|
||||
void WriteImpl()
|
||||
{
|
||||
lock (this)
|
||||
lock (semaphore)
|
||||
try
|
||||
{
|
||||
var fileHash = previousHash;
|
||||
|
||||
@@ -48,6 +48,11 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <inheritdoc />
|
||||
public Version DMApiVersion => throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for <see cref="disposed"/>.
|
||||
/// </summary>
|
||||
readonly object disposeLock;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="DeadSessionController"/> was <see cref="Dispose"/>d
|
||||
/// </summary>
|
||||
@@ -66,12 +71,13 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
});
|
||||
Lifetime = Task.FromResult(-1);
|
||||
OnReboot = new TaskCompletionSource<object>().Task;
|
||||
disposeLock = new object();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
lock (disposeLock)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
@@ -136,6 +136,11 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// </summary>
|
||||
readonly ILogger<SessionController> logger;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for port updates and <see cref="disposed"/>.
|
||||
/// </summary>
|
||||
readonly object synchronizationLock;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TaskCompletionSource{TResult}"/> <see cref="SetPort(ushort, CancellationToken)"/> waits on when DreamDaemon currently has it's ports closed
|
||||
/// </summary>
|
||||
@@ -214,6 +219,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
|
||||
rebootTcs = new TaskCompletionSource<object>();
|
||||
|
||||
synchronizationLock = new object();
|
||||
|
||||
CancellationTokenSource cts = null;
|
||||
Task lifetimeContinuation = null;
|
||||
lifetimeContinuation = process.Lifetime.ContinueWith(
|
||||
@@ -287,7 +294,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <param name="disposing">If this function was NOT called by the finalizer</param>
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
@@ -366,7 +373,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
process.Terminate();
|
||||
break;
|
||||
case BridgeCommandType.PortUpdate:
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (!parameters.CurrentPort.HasValue)
|
||||
{
|
||||
@@ -569,7 +576,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
return true;
|
||||
}
|
||||
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
if (portClosedForReboot)
|
||||
{
|
||||
if (portAssignmentTcs != null)
|
||||
|
||||
@@ -29,6 +29,11 @@ namespace Tgstation.Server.Host.Core
|
||||
/// </summary>
|
||||
readonly SemaphoreSlim lockedSemaphore;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for <see cref="disposed"/>.
|
||||
/// </summary>
|
||||
readonly object disposeLock;
|
||||
|
||||
/// <summary>
|
||||
/// If <see cref="Dispose"/> has been called
|
||||
/// </summary>
|
||||
@@ -41,6 +46,7 @@ namespace Tgstation.Server.Host.Core
|
||||
SemaphoreSlimContext(SemaphoreSlim lockedSemaphore)
|
||||
{
|
||||
this.lockedSemaphore = lockedSemaphore;
|
||||
disposeLock = new object();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,7 +61,7 @@ namespace Tgstation.Server.Host.Core
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
lock (disposeLock)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
@@ -28,6 +28,11 @@ namespace Tgstation.Server.Host.Jobs
|
||||
/// </summary>
|
||||
readonly Dictionary<long, JobHandler> jobs;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for various operations.
|
||||
/// </summary>
|
||||
readonly object synchronizationLock;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="JobManager"/>
|
||||
/// </summary>
|
||||
@@ -38,6 +43,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
jobs = new Dictionary<long, JobHandler>();
|
||||
synchronizationLock = new object();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -54,7 +60,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
/// <returns>The <see cref="JobHandler"/></returns>
|
||||
JobHandler CheckGetJob(Job job)
|
||||
{
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (!jobs.TryGetValue(job.Id, out JobHandler jobHandler))
|
||||
throw new InvalidOperationException("Job not running!");
|
||||
@@ -139,7 +145,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
var handler = jobs[job.Id];
|
||||
jobs.Remove(job.Id);
|
||||
@@ -178,12 +184,12 @@ namespace Tgstation.Server.Host.Jobs
|
||||
var jobHandler = new JobHandler(x => RunJob(job, (jobParam, serviceProvider, ct) =>
|
||||
operation(jobParam, serviceProvider, y =>
|
||||
{
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
if (jobs.TryGetValue(job.Id, out var handler))
|
||||
handler.Progress = y;
|
||||
}, ct),
|
||||
x));
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
jobs.Add(job.Id, jobHandler);
|
||||
});
|
||||
|
||||
@@ -264,7 +270,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
{
|
||||
if (job == null)
|
||||
throw new ArgumentNullException(nameof(job));
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (!jobs.TryGetValue(job.Id, out var handler))
|
||||
return null;
|
||||
@@ -280,7 +286,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
if (canceller == null)
|
||||
throw new ArgumentNullException(nameof(canceller));
|
||||
JobHandler handler;
|
||||
lock (this)
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (!jobs.TryGetValue(job.Id, out handler))
|
||||
return;
|
||||
|
||||
@@ -28,11 +28,6 @@ namespace Tgstation.Server.Host
|
||||
/// </summary>
|
||||
readonly IHostBuilder hostBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="Server"/>.
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRestartHandler"/>s to run when the <see cref="Server"/> restarts
|
||||
/// </summary>
|
||||
@@ -43,6 +38,11 @@ namespace Tgstation.Server.Host
|
||||
/// </summary>
|
||||
readonly string updatePath;
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="lock"/> <see cref="object"/> for certain restart related operations.
|
||||
/// </summary>
|
||||
readonly object restartLock;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="Server"/>
|
||||
/// </summary>
|
||||
@@ -72,17 +72,16 @@ namespace Tgstation.Server.Host
|
||||
/// Construct a <see cref="Server"/>
|
||||
/// </summary>
|
||||
/// <param name="hostBuilder">The value of <see cref="hostBuilder"/></param>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
|
||||
/// <param name="updatePath">The value of <see cref="updatePath"/></param>
|
||||
public Server(IHostBuilder hostBuilder, IIOManager ioManager, string updatePath)
|
||||
public Server(IHostBuilder hostBuilder, string updatePath)
|
||||
{
|
||||
this.hostBuilder = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.updatePath = updatePath;
|
||||
|
||||
hostBuilder.ConfigureServices(serviceCollection => serviceCollection.AddSingleton<IServerControl>(this));
|
||||
|
||||
restartHandlers = new List<IRestartHandler>();
|
||||
restartLock = new object();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -133,22 +132,22 @@ namespace Tgstation.Server.Host
|
||||
fsWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
try
|
||||
using var host = hostBuilder.Build();
|
||||
try
|
||||
{
|
||||
logger = host.Services.GetRequiredService<ILogger<Server>>();
|
||||
using (cancellationToken.Register(() => logger.LogInformation("Process termination requested!")))
|
||||
{
|
||||
logger = host.Services.GetRequiredService<ILogger<Server>>();
|
||||
using (cancellationToken.Register(() => logger.LogInformation("Process termination requested!")))
|
||||
{
|
||||
var generalConfigurationOptions = host.Services.GetRequiredService<IOptions<GeneralConfiguration>>();
|
||||
generalConfiguration = generalConfigurationOptions.Value;
|
||||
await host.RunAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CheckExceptionPropagation(ex);
|
||||
throw;
|
||||
var generalConfigurationOptions = host.Services.GetRequiredService<IOptions<GeneralConfiguration>>();
|
||||
generalConfiguration = generalConfigurationOptions.Value;
|
||||
await host.RunAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CheckExceptionPropagation(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
CheckExceptionPropagation(null);
|
||||
@@ -168,7 +167,7 @@ namespace Tgstation.Server.Host
|
||||
|
||||
logger.LogTrace("Begin ApplyUpdate...");
|
||||
|
||||
lock (this)
|
||||
lock (restartLock)
|
||||
{
|
||||
if (updating || RestartRequested)
|
||||
{
|
||||
@@ -241,14 +240,14 @@ namespace Tgstation.Server.Host
|
||||
|
||||
CheckSanity(false);
|
||||
|
||||
lock (this)
|
||||
lock (restartLock)
|
||||
if (!RestartRequested)
|
||||
{
|
||||
logger.LogTrace("Registering restart handler {0}...", handler);
|
||||
restartHandlers.Add(handler);
|
||||
return new RestartRegistration(() =>
|
||||
{
|
||||
lock (this)
|
||||
lock (restartLock)
|
||||
if (!RestartRequested)
|
||||
restartHandlers.Remove(handler);
|
||||
});
|
||||
@@ -273,7 +272,7 @@ namespace Tgstation.Server.Host
|
||||
|
||||
logger.LogTrace("Begin Restart...");
|
||||
|
||||
lock (this)
|
||||
lock (restartLock)
|
||||
{
|
||||
if ((updating && newVersion == null) || RestartRequested)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Tgstation.Server.Host
|
||||
IOManager.ResolvePath(
|
||||
IOManager.GetDirectoryName(assemblyInformationProvider.Path)));
|
||||
|
||||
return new Server(hostBuilder, IOManager, updatePath);
|
||||
return new Server(hostBuilder, updatePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user