SEBWIN-220: Introduced timeout for startup and shutdown of BaseHost.

This commit is contained in:
dbuechel 2018-10-02 08:02:48 +02:00
parent 86d6949a6f
commit c8001e85f6
10 changed files with 31 additions and 19 deletions

View file

@ -40,7 +40,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
sut = new ClientHost("net:pipe://some/address", hostObjectFactory.Object, logger.Object, PROCESS_ID);
sut = new ClientHost("net:pipe://some/address", hostObjectFactory.Object, logger.Object, PROCESS_ID, 0);
}
[TestMethod]

View file

@ -72,7 +72,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
clientHost.VerifyNoOtherCalls();
Assert.IsFalse(stopWatch.IsRunning);
Assert.IsTrue(stopWatch.ElapsedMilliseconds > timeout_ms);
Assert.IsTrue(stopWatch.ElapsedMilliseconds >= timeout_ms);
}
[TestMethod]

View file

@ -28,7 +28,12 @@ namespace SafeExamBrowser.Client.Communication
public event CommunicationEventHandler RuntimeDisconnected;
public event CommunicationEventHandler Shutdown;
public ClientHost(string address, IHostObjectFactory factory, ILogger logger, int processId) : base(address, factory, logger)
public ClientHost(
string address,
IHostObjectFactory factory,
ILogger logger,
int processId,
int timeout_ms) : base(address, factory, logger, timeout_ms)
{
this.processId = processId;
}

View file

@ -180,9 +180,10 @@ namespace SafeExamBrowser.Client
private IOperation BuildClientHostOperation()
{
const int FIVE_SECONDS = 5000;
var processId = Process.GetCurrentProcess().Id;
var factory = new HostObjectFactory();
var host = new ClientHost(configuration.AppConfig.ClientAddress, factory, new ModuleLogger(logger, nameof(ClientHost)), processId);
var host = new ClientHost(configuration.AppConfig.ClientAddress, factory, new ModuleLogger(logger, nameof(ClientHost)), processId, FIVE_SECONDS);
var operation = new CommunicationHostOperation(host, logger);
clientHost = host;

View file

@ -21,7 +21,7 @@ namespace SafeExamBrowser.Communication.UnitTests.Hosts
public Func<Message, Response> OnReceiveStub { get; set; }
public Func<SimpleMessagePurport, Response> OnReceiveSimpleMessageStub { get; set; }
public BaseHostStub(string address, IHostObjectFactory factory, ILogger logger) : base(address, factory, logger)
public BaseHostStub(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms) : base(address, factory, logger, timeout_ms)
{
}

View file

@ -35,7 +35,7 @@ namespace SafeExamBrowser.Communication.UnitTests.Hosts
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
sut = new BaseHostStub("net.pipe://some/address/here", hostObjectFactory.Object, logger.Object);
sut = new BaseHostStub("net.pipe://some/address/here", hostObjectFactory.Object, logger.Object, 10);
}
[TestMethod]
@ -56,7 +56,6 @@ namespace SafeExamBrowser.Communication.UnitTests.Hosts
[ExpectedException(typeof(CommunicationException))]
public void MustCorrectlyHandleStartupException()
{
// TODO: Takes waaay too long, extract timeout (move to constructor like in ClientOperation)!
hostObject.Setup(h => h.Open()).Throws<Exception>();
sut.Start();

View file

@ -22,13 +22,13 @@ namespace SafeExamBrowser.Communication.Hosts
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public abstract class BaseHost : ICommunication, ICommunicationHost
{
private const int FIVE_SECONDS = 5000;
private readonly object @lock = new object();
private string address;
private IHostObject host;
private IHostObjectFactory factory;
private Thread hostThread;
private int timeout_ms;
protected Guid? CommunicationToken { get; private set; }
protected ILogger Logger { get; private set; }
@ -44,11 +44,12 @@ namespace SafeExamBrowser.Communication.Hosts
}
}
public BaseHost(string address, IHostObjectFactory factory, ILogger logger)
public BaseHost(string address, IHostObjectFactory factory, ILogger logger, int timeout_ms)
{
this.address = address;
this.factory = factory;
this.Logger = logger;
this.timeout_ms = timeout_ms;
}
protected abstract bool OnConnect(Guid? token);
@ -137,11 +138,11 @@ namespace SafeExamBrowser.Communication.Hosts
hostThread.IsBackground = true;
hostThread.Start();
var success = startedEvent.WaitOne(FIVE_SECONDS);
var success = startedEvent.WaitOne(timeout_ms);
if (!success)
{
throw new CommunicationException($"Failed to start communication host for endpoint '{address}' within {FIVE_SECONDS / 1000} seconds!", exception);
throw new CommunicationException($"Failed to start communication host for endpoint '{address}' within {timeout_ms / 1000} seconds!", exception);
}
}
}
@ -202,7 +203,7 @@ namespace SafeExamBrowser.Communication.Hosts
try
{
host?.Close();
success = hostThread?.Join(FIVE_SECONDS) == true;
success = hostThread?.Join(timeout_ms) == true;
}
catch (Exception e)
{

View file

@ -37,7 +37,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
sut = new RuntimeHost("net:pipe://some/address", configuration.Object, hostObjectFactory.Object, logger.Object);
sut = new RuntimeHost("net:pipe://some/address", configuration.Object, hostObjectFactory.Object, logger.Object, 0);
}
[TestMethod]

View file

@ -7,12 +7,12 @@
*/
using System;
using SafeExamBrowser.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Data;
using SafeExamBrowser.Contracts.Communication.Events;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Communication.Hosts;
namespace SafeExamBrowser.Runtime.Communication
{
@ -29,7 +29,12 @@ namespace SafeExamBrowser.Runtime.Communication
public event CommunicationEventHandler<ReconfigurationEventArgs> ReconfigurationRequested;
public event CommunicationEventHandler ShutdownRequested;
public RuntimeHost(string address, IConfigurationRepository configuration, IHostObjectFactory factory, ILogger logger) : base(address, factory, logger)
public RuntimeHost(
string address,
IConfigurationRepository configuration,
IHostObjectFactory factory,
ILogger logger,
int timeout_ms) : base(address, factory, logger, timeout_ms)
{
this.configuration = configuration;
}

View file

@ -41,7 +41,8 @@ namespace SafeExamBrowser.Runtime
internal void BuildObjectGraph(Action shutdown)
{
const int STARTUP_TIMEOUT_MS = 15000;
const int FIVE_SECONDS = 5000;
const int FIFTEEN_SECONDS = 15000;
var args = Environment.GetCommandLineArgs();
var configuration = BuildConfigurationRepository();
@ -60,7 +61,7 @@ namespace SafeExamBrowser.Runtime
var processFactory = new ProcessFactory(new ModuleLogger(logger, nameof(ProcessFactory)));
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), logger);
var resourceLoader = new ResourceLoader();
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, configuration, new HostObjectFactory(), new ModuleLogger(logger, nameof(RuntimeHost)));
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, configuration, new HostObjectFactory(), new ModuleLogger(logger, nameof(RuntimeHost)), FIVE_SECONDS);
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(ServiceProxy)));
var uiFactory = new UserInterfaceFactory(text);
@ -73,9 +74,9 @@ namespace SafeExamBrowser.Runtime
sessionOperations.Enqueue(new ConfigurationOperation(appConfig, configuration, logger, messageBox, resourceLoader, runtimeHost, text, uiFactory, args));
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost));
sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy, text));
sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, STARTUP_TIMEOUT_MS));
sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, FIFTEEN_SECONDS));
sessionOperations.Enqueue(new KioskModeOperation(configuration, desktopFactory, explorerShell, logger, processFactory));
sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, STARTUP_TIMEOUT_MS));
sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, FIFTEEN_SECONDS));
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
var sessionSequence = new OperationSequence(logger, sessionOperations);