diff --git a/build/Version.props b/build/Version.props
index b169916252..34c362b277 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -3,8 +3,8 @@
4.2.1
- 6.2.0
- 6.1.0
+ 6.3.0
+ 6.2.0
5.1.1
0.4.0
1.1.0
diff --git a/src/Tgstation.Server.Api/Models/ErrorCode.cs b/src/Tgstation.Server.Api/Models/ErrorCode.cs
index 9de878067c..f36699047d 100644
--- a/src/Tgstation.Server.Api/Models/ErrorCode.cs
+++ b/src/Tgstation.Server.Api/Models/ErrorCode.cs
@@ -471,5 +471,11 @@ namespace Tgstation.Server.Api.Models
///
[Description("Cannot set both softShutdown and softReboot at once!")]
DreamDaemonDoubleSoft,
+
+ ///
+ /// Attempted to launch DreamDaemon on a user account that had the BYOND pager running.
+ ///
+ [Description("Cannot start DreamDaemon headless with the BYOND pager running!")]
+ DeploymentPagerRunning,
}
}
\ No newline at end of file
diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
index 92a76a973b..8f5bb7db31 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
@@ -201,7 +201,7 @@ namespace Tgstation.Server.Host.Components.Session
if (launchParameters.SecurityLevel == DreamDaemonSecurity.Trusted)
await byondLock.TrustDmbPath(ioManager.ConcatPath(basePath, dmbProvider.DmbName), cancellationToken).ConfigureAwait(false);
- CheckPagerIsNotRunning();
+ await CheckPagerIsNotRunning(cancellationToken).ConfigureAwait(false);
var accessIdentifier = cryptographySuite.GetSecureString();
@@ -403,10 +403,24 @@ namespace Tgstation.Server.Host.Components.Session
///
/// Make sure the BYOND pager is not running.
///
- void CheckPagerIsNotRunning()
+ /// The for the operation.
+ /// A representing the running operation.
+ async Task CheckPagerIsNotRunning(CancellationToken cancellationToken)
{
- if (platformIdentifier.IsWindows && processExecutor.IsProcessWithNameRunning("byond"))
- throw new JobException("Cannot start DreamDaemon headless with the BYOND pager running!");
+ if (!platformIdentifier.IsWindows)
+ return;
+
+ using var otherProcess = processExecutor.GetProcessByName("byond");
+ if (otherProcess == null)
+ return;
+
+ var otherUsernameTask = otherProcess.GetExecutingUsername(cancellationToken);
+ using var ourProcess = processExecutor.GetCurrentProcess();
+ var ourUserName = await ourProcess.GetExecutingUsername(cancellationToken).ConfigureAwait(false);
+ var otherUserName = await otherUsernameTask.ConfigureAwait(false);
+
+ if(otherUserName.Equals(ourUserName, StringComparison.Ordinal))
+ throw new JobException(ErrorCode.DeploymentPagerRunning);
}
}
}
diff --git a/src/Tgstation.Server.Host/System/IProcessExecutor.cs b/src/Tgstation.Server.Host/System/IProcessExecutor.cs
index 6b732915dd..3dea91680b 100644
--- a/src/Tgstation.Server.Host/System/IProcessExecutor.cs
+++ b/src/Tgstation.Server.Host/System/IProcessExecutor.cs
@@ -18,17 +18,23 @@
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments = null, bool readOutput = false, bool readError = false, bool noShellExecute = false);
///
- /// Get a by
+ /// Get a representing the running executable.
///
- /// The
- /// The represented by on success, on failure
+ /// The current .
+ IProcess GetCurrentProcess();
+
+ ///
+ /// Get a by .
+ ///
+ /// The .
+ /// The represented by on success, on failure.
IProcess GetProcess(int id);
///
- /// Check if a with a given is running.
+ /// Get a with a given .
///
- /// The name of the process without the extension.
- /// if the process is running, otherwise.
- bool IsProcessWithNameRunning(string name);
+ /// The name of the process executable without the extension.
+ /// The represented by on success, on failure.
+ IProcess GetProcessByName(string name);
}
}
diff --git a/src/Tgstation.Server.Host/System/ProcessExecutor.cs b/src/Tgstation.Server.Host/System/ProcessExecutor.cs
index 66841aad75..9284a0703e 100644
--- a/src/Tgstation.Server.Host/System/ProcessExecutor.cs
+++ b/src/Tgstation.Server.Host/System/ProcessExecutor.cs
@@ -1,6 +1,5 @@
using Microsoft.Extensions.Logging;
using System;
-using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -83,23 +82,15 @@ namespace Tgstation.Server.Host.System
return null;
}
- try
- {
- return new Process(
- processFeatures,
- handle,
- AttachExitHandler(handle),
- null,
- null,
- null,
- loggerFactory.CreateLogger(),
- true);
- }
- catch
- {
- handle.Dispose();
- throw;
- }
+ return CreateFromExistingHandle(handle);
+ }
+
+ ///
+ public IProcess GetCurrentProcess()
+ {
+ logger.LogTrace("Getting current process...");
+ var handle = global::System.Diagnostics.Process.GetCurrentProcess();
+ return CreateFromExistingHandle(handle);
}
///
@@ -231,13 +222,50 @@ namespace Tgstation.Server.Host.System
}
///
- public bool IsProcessWithNameRunning(string name)
+ public IProcess GetProcessByName(string name)
{
+ logger.LogTrace("GetProcessByName: {0}...", name ?? throw new ArgumentNullException(nameof(name)));
var procs = global::System.Diagnostics.Process.GetProcessesByName(name);
+ global::System.Diagnostics.Process handle = null;
foreach (var proc in procs)
- proc.Dispose();
+ if (handle == null)
+ handle = proc;
+ else
+ {
+ logger.LogTrace("Disposing extra found PID: {0}", proc.Id);
+ proc.Dispose();
+ }
- return procs.Any();
+ if (handle == null)
+ return null;
+
+ return CreateFromExistingHandle(handle);
+ }
+
+ ///
+ /// Create a given an existing .
+ ///
+ /// The to create a from.
+ /// The based on .
+ private IProcess CreateFromExistingHandle(global::System.Diagnostics.Process handle)
+ {
+ try
+ {
+ return new Process(
+ processFeatures,
+ handle,
+ AttachExitHandler(handle),
+ null,
+ null,
+ null,
+ loggerFactory.CreateLogger(),
+ true);
+ }
+ catch
+ {
+ handle.Dispose();
+ throw;
+ }
}
}
}
diff --git a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs
index 20e691b1e2..f7a8ed3e55 100644
--- a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs
+++ b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs
@@ -12,6 +12,7 @@ using Tgstation.Server.Api.Models;
using Tgstation.Server.Client;
using Tgstation.Server.Client.Components;
using Tgstation.Server.Host.Components.Interop;
+using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.System;
namespace Tgstation.Server.Tests.Instance
@@ -102,7 +103,7 @@ namespace Tgstation.Server.Tests.Instance
using var ourProcessHandler = new ProcessExecutor(
new PlatformIdentifier().IsWindows
? (IProcessFeatures)new WindowsProcessFeatures(Mock.Of>())
- : new PosixProcessFeatures(Mock.Of>()),
+ : new PosixProcessFeatures(Mock.Of(), Mock.Of>()),
Mock.Of>(),
LoggerFactory.Create(x => { }))
.GetProcess(ddProc.Id);