fix hangs due to uncleared TCS in IntegrationTesting (#1008)
This commit is contained in:
parent
39164eeb40
commit
ad79cdd123
|
|
@ -1,35 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace System.Threading.Tasks
|
|
||||||
{
|
|
||||||
internal static class TaskTimeoutExtensions
|
|
||||||
{
|
|
||||||
public static async Task OrTimeout(this Task task, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
var completed = await Task.WhenAny(task, Task.Delay(timeout));
|
|
||||||
if (completed == task)
|
|
||||||
{
|
|
||||||
// Manifest any exception
|
|
||||||
task.GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new TimeoutException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<T> OrTimeout<T>(this Task<T> task, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
var completed = await Task.WhenAny(task, Task.Delay(timeout));
|
|
||||||
if (completed == task)
|
|
||||||
{
|
|
||||||
return await task;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new TimeoutException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,7 @@ using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
@ -213,6 +214,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
process.Exited += (sender, e) =>
|
process.Exited += (sender, e) =>
|
||||||
{
|
{
|
||||||
Logger.LogInformation("iisexpress Process {pid} shut down", process.Id);
|
Logger.LogInformation("iisexpress Process {pid} shut down", process.Id);
|
||||||
|
|
||||||
|
// If TrySetResult was called above, this will just silently fail to set the new state, which is what we want
|
||||||
|
started.TrySetException(new Exception($"Command exited unexpectedly with exit code: {process.ExitCode}"));
|
||||||
|
|
||||||
TriggerHostShutdown(hostExitTokenSource);
|
TriggerHostShutdown(hostExitTokenSource);
|
||||||
};
|
};
|
||||||
process.StartAndCaptureOutAndErrToLogger("iisexpress", Logger);
|
process.StartAndCaptureOutAndErrToLogger("iisexpress", Logger);
|
||||||
|
|
@ -225,7 +230,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the app to start
|
// Wait for the app to start
|
||||||
if (!await started.Task)
|
// The timeout here is large, because we don't know how long the test could need
|
||||||
|
// We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build
|
||||||
|
// just in case we missed one -anurse
|
||||||
|
if (!await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10)))
|
||||||
{
|
{
|
||||||
Logger.LogInformation("iisexpress Process {pid} failed to bind to port {port}, trying again", _hostProcess.Id, port);
|
Logger.LogInformation("iisexpress Process {pid} failed to bind to port {port}, trying again", _hostProcess.Id, port);
|
||||||
|
|
||||||
|
|
@ -294,7 +302,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
||||||
// If by this point, the host process is still running (somehow), throw an error.
|
// If by this point, the host process is still running (somehow), throw an error.
|
||||||
// A test failure is better than a silent hang and unknown failure later on
|
// A test failure is better than a silent hang and unknown failure later on
|
||||||
if(!_hostProcess.HasExited)
|
if (!_hostProcess.HasExited)
|
||||||
{
|
{
|
||||||
throw new Exception($"iisexpress Process {_hostProcess.Id} failed to shutdown");
|
throw new Exception($"iisexpress Process {_hostProcess.Id} failed to shutdown");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
@ -140,6 +141,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
HostProcess.Exited += (sender, e) =>
|
HostProcess.Exited += (sender, e) =>
|
||||||
{
|
{
|
||||||
Logger.LogInformation("host process ID {pid} shut down", HostProcess.Id);
|
Logger.LogInformation("host process ID {pid} shut down", HostProcess.Id);
|
||||||
|
|
||||||
|
// If TrySetResult was called above, this will just silently fail to set the new state, which is what we want
|
||||||
|
started.TrySetException(new Exception($"Command exited unexpectedly with exit code: {HostProcess.ExitCode}"));
|
||||||
|
|
||||||
TriggerHostShutdown(hostExitTokenSource);
|
TriggerHostShutdown(hostExitTokenSource);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -160,7 +165,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
||||||
Logger.LogInformation("Started {fileName}. Process Id : {processId}", startInfo.FileName, HostProcess.Id);
|
Logger.LogInformation("Started {fileName}. Process Id : {processId}", startInfo.FileName, HostProcess.Id);
|
||||||
|
|
||||||
await started.Task;
|
// The timeout here is large, because we don't know how long the test could need
|
||||||
|
// We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build
|
||||||
|
// just in case we missed one -anurse
|
||||||
|
await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10));
|
||||||
|
|
||||||
return (url: actualUrl ?? hintUrl, hostExitToken: hostExitTokenSource.Token);
|
return (url: actualUrl ?? hintUrl, hostExitToken: hostExitTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue