diff --git a/.github/workflows/ci-suite.yml b/.github/workflows/ci-suite.yml index ccdaa58af9..1e2b15aef8 100644 --- a/.github/workflows/ci-suite.yml +++ b/.github/workflows/ci-suite.yml @@ -146,7 +146,7 @@ jobs: doxyfile-path: 'docs/Doxyfile' - name: gh-pages push - if: github.event_name == 'push' && github.event.ref == 'refs/heads/dev' + if: github.event_name == 'push' && github.event.ref == 'refs/heads/dev' && env.TGS_RELEASE_NOTES_TOKEN != '' run: | git clone -b gh-pages --single-branch "https://git@github.com/tgstation/tgstation-server" $HOME/tgsdox pushd $HOME/tgsdox diff --git a/SECURITY.md b/SECURITY.md index 5d79c18579..1e624e68bb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,6 +16,6 @@ Vulnerabilities should ideally be reported by directly messaging one of the TGS Here is a list of their discord IDs. -@Cyberboss - Dominion#0444 (<@133295178197893120>) +@Cyberboss - dominion (<@133295178197893120>) Once reported, they will handle the processing of the security advisory. diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs index f9ef3396c6..bfc541e6f9 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs @@ -309,7 +309,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers cancellationToken); // DCT: Always wait for the job to complete here - await jobManager.WaitForJobCompletion(job, null, cancellationToken, default); + await jobManager.WaitForJobCompletion(job, null, cancellationToken, cancellationToken); } } catch (OperationCanceledException e) diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index 95ca246c42..0e441edb15 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -514,11 +514,9 @@ namespace Tgstation.Server.Host.Components await jobManager.RegisterOperation( repositoryUpdateJob, RepositoryAutoUpdateJob, - cancellationToken) - ; + cancellationToken); - // DCT: First token will cancel the job, second is for cancelling the cancellation, unwanted - await jobManager.WaitForJobCompletion(repositoryUpdateJob, null, cancellationToken, default); + await jobManager.WaitForJobCompletion(repositoryUpdateJob, null, cancellationToken, cancellationToken); Job compileProcessJob; using (var repo = await RepositoryManager.LoadRepository(cancellationToken)) diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs index 725f99fb3a..258ab9709c 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs @@ -854,7 +854,7 @@ namespace Tgstation.Server.Host.Components.Watchdog var heartbeatSeconds = ActiveLaunchParameters.HeartbeatSeconds.Value; var heartbeat = heartbeatSeconds == 0 || !controller.DMApiAvailable - ? Extensions.TaskExtensions.InfiniteTask() + ? Extensions.TaskExtensions.InfiniteTask : Task.Delay( TimeSpan.FromSeconds(heartbeatSeconds), cancellationToken); diff --git a/src/Tgstation.Server.Host/Extensions/TaskExtensions.cs b/src/Tgstation.Server.Host/Extensions/TaskExtensions.cs index a8ee467d1e..bd65a629d9 100644 --- a/src/Tgstation.Server.Host/Extensions/TaskExtensions.cs +++ b/src/Tgstation.Server.Host/Extensions/TaskExtensions.cs @@ -14,6 +14,11 @@ namespace Tgstation.Server.Host.Extensions /// static readonly TaskCompletionSource InfiniteTaskCompletionSource = new (); + /// + /// Gets a that never completes. + /// + public static Task InfiniteTask => InfiniteTaskCompletionSource.Task; + /// /// Create a that can be awaited while respecting a given . /// @@ -53,11 +58,5 @@ namespace Tgstation.Server.Host.Extensions return await task; } - - /// - /// Creates a that never completes. - /// - /// A never ending . - public static Task InfiniteTask() => InfiniteTaskCompletionSource.Task; } } diff --git a/src/Tgstation.Server.Host/Jobs/JobHandler.cs b/src/Tgstation.Server.Host/Jobs/JobHandler.cs index 19941fbefd..98cbe88651 100644 --- a/src/Tgstation.Server.Host/Jobs/JobHandler.cs +++ b/src/Tgstation.Server.Host/Jobs/JobHandler.cs @@ -11,6 +11,21 @@ namespace Tgstation.Server.Host.Jobs /// sealed class JobHandler : IDisposable { + /// + /// If the job has started. + /// + public bool Started => task != null; + + /// + /// The progress of the job. + /// + public int? Progress { get; set; } + + /// + /// The stage of the job. + /// + public string Stage { get; set; } + /// /// The for . /// @@ -39,16 +54,6 @@ namespace Tgstation.Server.Host.Jobs /// public void Dispose() => cancellationTokenSource.Dispose(); - /// - /// The progress of the job. - /// - public int? Progress { get; set; } - - /// - /// The stage of the job. - /// - public string Stage { get; set; } - /// /// Wait for to complete. /// diff --git a/src/Tgstation.Server.Host/Jobs/JobService.cs b/src/Tgstation.Server.Host/Jobs/JobService.cs index c0d01f2dcf..971150061a 100644 --- a/src/Tgstation.Server.Host/Jobs/JobService.cs +++ b/src/Tgstation.Server.Host/Jobs/JobService.cs @@ -256,13 +256,23 @@ namespace Tgstation.Server.Host.Jobs { if (job == null) throw new ArgumentNullException(nameof(job)); + + if (!cancellationToken.CanBeCanceled) + throw new ArgumentException("A cancellable CancellationToken should be provided!", nameof(cancellationToken)); + JobHandler handler; + bool noMoreJobsShouldStart; lock (synchronizationLock) { if (!jobs.TryGetValue(job.Id.Value, out handler)) return; + + noMoreJobsShouldStart = this.noMoreJobsShouldStart; } + if (noMoreJobsShouldStart && !handler.Started) + await Extensions.TaskExtensions.InfiniteTask.WithToken(cancellationToken); + Task cancelTask = null; using (jobCancellationToken.Register(() => cancelTask = CancelJob(job, canceller, true, cancellationToken))) await handler.Wait(cancellationToken); diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs index d53456c8ac..8f8a5ce7a9 100644 --- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs +++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs @@ -380,7 +380,7 @@ namespace Tgstation.Server.Host.Swarm ? asyncDelayer.Delay( TimeSpan.FromMinutes(UpdateCommitTimeoutMinutes), cancellationToken) - : Extensions.TaskExtensions.InfiniteTask().WithToken(cancellationToken); + : Extensions.TaskExtensions.InfiniteTask.WithToken(cancellationToken); var commitTask = Task.WhenAny(commitTcsTask, timeoutTask); diff --git a/tests/Tgstation.Server.Tests/Live/Instance/RepositoryTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/RepositoryTest.cs index c35ccd70dd..05f3b90ec2 100644 --- a/tests/Tgstation.Server.Tests/Live/Instance/RepositoryTest.cs +++ b/tests/Tgstation.Server.Tests/Live/Instance/RepositoryTest.cs @@ -59,8 +59,8 @@ namespace Tgstation.Server.Tests.Live.Instance if (!targetActiveJob.Progress.HasValue) { - // give it 15 more seconds - targetActiveJob = await WaitForJobProgress(targetActiveJob, 15, cancellationToken); + // give it a few more seconds + targetActiveJob = await WaitForJobProgress(targetActiveJob, 30, cancellationToken); allJobs = await JobsClient.List(null, cancellationToken); } diff --git a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs index 3b08f87812..c97cac3308 100644 --- a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs +++ b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs @@ -246,7 +246,14 @@ namespace Tgstation.Server.Tests.Live.Instance jobTcs.SetResult(); await killTask; } - Assert.IsTrue(job.ErrorCode == ErrorCode.DreamDaemonOffline || job.ErrorCode == ErrorCode.GCoreFailure, $"{job.ErrorCode}: {job.ExceptionDetails}"); + + // these can also happen + if (!(new PlatformIdentifier().IsWindows + && (job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_ACCESSDENIED: Access is denied.") + || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_HANDLE: The handle is invalid.") + || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: 3489660936: Unknown error (0xd0000008)")))) // kek + Assert.IsTrue(job.ErrorCode == ErrorCode.DreamDaemonOffline || job.ErrorCode == ErrorCode.GCoreFailure, $"{job.ErrorCode}: {job.ExceptionDetails}"); + await Task.Delay(TimeSpan.FromSeconds(20), cancellationToken); var ddStatus = await instanceClient.DreamDaemon.Read(cancellationToken); @@ -531,7 +538,7 @@ namespace Tgstation.Server.Tests.Live.Instance TopicResponse topicRequestResult = null; try { - System.Console.WriteLine($"Topic limit test S:{payloadSize}..."); + System.Console.WriteLine($"Topic send limit test S:{currentSize}..."); topicRequestResult = await TopicClientNoLogger.SendTopic( IPAddress.Loopback, $"tgs_integration_test_tactics3={TopicClient.SanitizeString(JsonConvert.SerializeObject(topic, DMApiConstants.SerializerSettings))}", @@ -563,6 +570,8 @@ namespace Tgstation.Server.Tests.Live.Instance Assert.AreEqual(DMApiConstants.MaximumTopicRequestLength, (uint)lastSize); + System.Console.WriteLine("TEST: Receiving Topic tests topics..."); + // Receive baseSize = 1; nextPow = 0; @@ -570,6 +579,7 @@ namespace Tgstation.Server.Tests.Live.Instance while (!cancellationToken.IsCancellationRequested) { var currentSize = baseSize + (int)Math.Pow(2, nextPow); + System.Console.WriteLine($"Topic recieve limit test S:{currentSize}..."); var topicRequestResult = await TopicClientNoLogger.SendTopic( IPAddress.Loopback, $"tgs_integration_test_tactics4={TopicClient.SanitizeString(currentSize.ToString())}",