Watchdog for life

This commit is contained in:
Cyberboss
2018-05-02 16:41:10 -04:00
parent d6d62b278b
commit 4ac4f3f987
7 changed files with 26 additions and 22 deletions
@@ -33,9 +33,9 @@ namespace Tgstation.Server.Host.Components
}
/// <summary>
/// The <see cref="IInstanceShutdownMethod"/> for the <see cref="DreamDaemonExecutor"/>
/// The <see cref="IInstanceShutdownHandler"/> for the <see cref="DreamDaemonExecutor"/>
/// </summary>
readonly IInstanceShutdownMethod instanceShutdownMethod;
readonly IInstanceShutdownHandler instanceShutdownMethod;
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="DreamDaemonExecutor"/>
/// </summary>
@@ -46,14 +46,14 @@ namespace Tgstation.Server.Host.Components
/// </summary>
/// <param name="instanceShutdownMethod">The value of <see cref="instanceShutdownMethod"/></param>
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
public DreamDaemonExecutor(IInstanceShutdownMethod instanceShutdownMethod, IIOManager ioManager)
public DreamDaemonExecutor(IInstanceShutdownHandler instanceShutdownMethod, IIOManager ioManager)
{
this.instanceShutdownMethod = instanceShutdownMethod ?? throw new ArgumentNullException(nameof(instanceShutdownMethod));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
}
/// <inheritdoc />
public async Task<int> RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, TaskCompletionSource<object> onSuccessfulStartup, string dreamDaemonPath, string dmbPath, string accessToken, bool usePrimaryPort, CancellationToken cancellationToken)
public async Task<int> RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, TaskCompletionSource<object> onSuccessfulStartup, string dreamDaemonPath, string dmbPath, string accessToken, bool usePrimaryPort, bool alwaysKill, CancellationToken cancellationToken)
{
using (var proc = new Process())
{
@@ -85,7 +85,7 @@ namespace Tgstation.Server.Host.Components
}
finally
{
if (!instanceShutdownMethod.GracefulShutdown)
if (!alwaysKill && !await instanceShutdownMethod.PreserveActiveExecutablesIfNecessary(launchParameters, accessToken, proc.Id, usePrimaryPort).ConfigureAwait(false))
{
proc.Kill();
proc.WaitForExit();
@@ -18,8 +18,9 @@ namespace Tgstation.Server.Host.Components
/// <param name="dmbPath">The path to the .dmb to run, the working directory will be derived from this</param>
/// <param name="accessToken">The access token to be used for communication</param>
/// <param name="usePrimaryPort">If the server should open on <see cref="DreamDaemonLaunchParameters.PrimaryPort"/> or <see cref="DreamDaemonLaunchParameters.SecondaryPort"/> of <paramref name="launchParameters"/></param>
/// <param name="alwaysKill">If the resulting process should never be left alive</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task{TResult}"/> representing the lifetime of the process and resulting in the exit code</returns>
Task<int> RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, TaskCompletionSource<object> onSuccessfulStartup, string dreamDaemonPath, string dmbPath, string accessToken, bool usePrimaryPort, CancellationToken cancellationToken);
Task<int> RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, TaskCompletionSource<object> onSuccessfulStartup, string dreamDaemonPath, string dmbPath, string accessToken, bool usePrimaryPort, bool alwaysKill, CancellationToken cancellationToken);
}
}
@@ -6,7 +6,7 @@ namespace Tgstation.Server.Host.Components
/// <summary>
/// For managing <see cref="IInstance"/>s
/// </summary>
interface IInstanceManager : IInstanceShutdownMethod
interface IInstanceManager : IInstanceShutdownHandler
{
/// <summary>
/// Get the <see cref="IInstance"/> associated with given <paramref name="metadata"/>
@@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Components
{
interface IInstanceShutdownHandler
{
Task<bool> PreserveActiveExecutablesIfNecessary(DreamDaemonLaunchParameters launchParameters, string accessToken, int pid, bool primary);
}
}
@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Tgstation.Server.Host.Components
{
interface IInstanceShutdownMethod
{
bool GracefulShutdown { get; set; }
}
}
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Models;
@@ -14,9 +15,6 @@ namespace Tgstation.Server.Host.Components
/// <inheritdoc />
sealed class InstanceManager : IInstanceManager, IHostedService
{
/// <inheritdoc />
public bool GracefulShutdown { get; set; }
/// <summary>
/// The <see cref="IInstanceFactory"/> for the <see cref="IInstanceManager"/>
/// </summary>
@@ -131,5 +129,11 @@ namespace Tgstation.Server.Host.Components
await Task.WhenAll(instances.Select(x => x.Value.StopAsync(cancellationToken))).ConfigureAwait(false);
instances.Clear();
}
/// <inheritdoc />
public Task<bool> PreserveActiveExecutablesIfNecessary(DreamDaemonLaunchParameters launchParameters, string accessToken, int pid, bool primary)
{
throw new NotImplementedException();
}
}
}
@@ -78,7 +78,7 @@ namespace Tgstation.Server.Host.Components
async Task<int> RunServer(DreamDaemonLaunchParameters launchParameters, TaskCompletionSource<object> onSuccessfulStartup, string accessToken, string dreamDaemonPath, bool isPrimary, CancellationToken cancellationToken)
{
using (var dmb = await dmbFactory.LockNextDmb(cancellationToken).ConfigureAwait(false))
return await dreamDaemonExecutor.RunDreamDaemon(launchParameters, onSuccessfulStartup, dreamDaemonPath, String.Concat(dmb.PrimaryDirectory, dmb.DmbName), accessToken, isPrimary, cancellationToken).ConfigureAwait(false);
return await dreamDaemonExecutor.RunDreamDaemon(launchParameters, onSuccessfulStartup, dreamDaemonPath, String.Concat(dmb.PrimaryDirectory, dmb.DmbName), accessToken, isPrimary, false, cancellationToken).ConfigureAwait(false);
}
/// <summary>