Avoid null refs in BlazorIgntior when Disposed (#14341)

* Avoid null refs in BlazorIgntior when Disposed

Fixes https://github.com/aspnet/AspNetCore/issues/14257
This commit is contained in:
Pranav K 2019-09-25 15:01:35 -07:00 committed by GitHub
commit 1937c804fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 65 deletions

View File

@ -27,6 +27,7 @@ Building ASP.NET Core on Windows requires:
```ps1
PS> ./eng/scripts/InstallJdk.ps1
```
* Chrome - Selenium-based tests require a version of Chrome to be installed. Download and install it from [https://www.google.com/chrome]
### macOS/Linux

View File

@ -88,7 +88,7 @@ namespace Ignitor
public Task<CapturedRenderBatch> PrepareForNextBatch(TimeSpan? timeout)
{
if (NextBatchReceived?.Completion != null)
if (NextBatchReceived != null && !NextBatchReceived.Disposed)
{
throw new InvalidOperationException("Invalid state previous task not completed");
}
@ -100,7 +100,7 @@ namespace Ignitor
public Task<CapturedJSInteropCall> PrepareForNextJSInterop(TimeSpan? timeout)
{
if (NextJSInteropReceived?.Completion != null)
if (NextJSInteropReceived != null && !NextJSInteropReceived.Disposed)
{
throw new InvalidOperationException("Invalid state previous task not completed");
}
@ -112,7 +112,7 @@ namespace Ignitor
public Task<string> PrepareForNextDotNetInterop(TimeSpan? timeout)
{
if (NextDotNetInteropCompletionReceived?.Completion != null)
if (NextDotNetInteropCompletionReceived != null && !NextDotNetInteropCompletionReceived.Disposed)
{
throw new InvalidOperationException("Invalid state previous task not completed");
}
@ -124,7 +124,7 @@ namespace Ignitor
public Task<string> PrepareForNextCircuitError(TimeSpan? timeout)
{
if (NextErrorReceived?.Completion != null)
if (NextErrorReceived != null && !NextErrorReceived.Disposed)
{
throw new InvalidOperationException("Invalid state previous task not completed");
}
@ -136,7 +136,7 @@ namespace Ignitor
public Task<Exception> PrepareForNextDisconnect(TimeSpan? timeout)
{
if (NextDisconnect?.Completion != null)
if (NextDisconnect != null && !NextDisconnect.Disposed)
{
throw new InvalidOperationException("Invalid state previous task not completed");
}
@ -499,56 +499,6 @@ namespace Ignitor
return element;
}
private class CancellableOperation<TResult>
{
public CancellableOperation(TimeSpan? timeout)
{
Timeout = timeout;
Initialize();
}
public TimeSpan? Timeout { get; }
public TaskCompletionSource<TResult> Completion { get; set; }
public CancellationTokenSource Cancellation { get; set; }
public CancellationTokenRegistration CancellationRegistration { get; set; }
private void Initialize()
{
Completion = new TaskCompletionSource<TResult>(TaskContinuationOptions.RunContinuationsAsynchronously);
Completion.Task.ContinueWith(
(task, state) =>
{
var operation = (CancellableOperation<TResult>)state;
operation.Dispose();
},
this,
TaskContinuationOptions.ExecuteSynchronously); // We need to execute synchronously to clean-up before anything else continues
if (Timeout != null && Timeout != System.Threading.Timeout.InfiniteTimeSpan && Timeout != TimeSpan.MaxValue)
{
Cancellation = new CancellationTokenSource(Timeout.Value);
CancellationRegistration = Cancellation.Token.Register(
(self) =>
{
var operation = (CancellableOperation<TResult>)self;
operation.Completion.TrySetCanceled(operation.Cancellation.Token);
operation.Cancellation.Dispose();
operation.CancellationRegistration.Dispose();
},
this);
}
}
private void Dispose()
{
Completion = null;
Cancellation.Dispose();
CancellationRegistration.Dispose();
}
}
private string[] ReadMarkers(string content)
{
content = content.Replace("\r\n", "").Replace("\n", "");

View File

@ -0,0 +1,64 @@
// 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.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ignitor
{
internal class CancellableOperation<TResult>
{
public CancellableOperation(TimeSpan? timeout)
{
Timeout = timeout;
Completion = new TaskCompletionSource<TResult>(TaskContinuationOptions.RunContinuationsAsynchronously);
Completion.Task.ContinueWith(
(task, state) =>
{
var operation = (CancellableOperation<TResult>)state;
operation.Dispose();
},
this,
TaskContinuationOptions.ExecuteSynchronously); // We need to execute synchronously to clean-up before anything else continues
if (Timeout != null && Timeout != System.Threading.Timeout.InfiniteTimeSpan && Timeout != TimeSpan.MaxValue)
{
Cancellation = new CancellationTokenSource(Timeout.Value);
CancellationRegistration = Cancellation.Token.Register(
(self) =>
{
var operation = (CancellableOperation<TResult>)self;
operation.Completion.TrySetCanceled(operation.Cancellation.Token);
operation.Cancellation.Dispose();
operation.CancellationRegistration.Dispose();
},
this);
}
}
public TimeSpan? Timeout { get; }
public TaskCompletionSource<TResult> Completion { get; }
public CancellationTokenSource Cancellation { get; }
public CancellationTokenRegistration CancellationRegistration { get; }
public bool Disposed { get; private set; }
private void Dispose()
{
if (Disposed)
{
return;
}
Disposed = true;
Completion.TrySetCanceled(Cancellation.Token);
Cancellation.Dispose();
CancellationRegistration.Dispose();
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.E2ETesting
var instance = await SeleniumStandaloneServer.GetInstanceAsync(output);
var attempt = 0;
var maxAttempts = 3;
const int maxAttempts = 3;
do
{
try
@ -132,18 +132,16 @@ namespace Microsoft.AspNetCore.E2ETesting
return (driver, logs);
}
catch
catch (Exception ex)
{
if (attempt >= maxAttempts)
{
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive");
}
output.WriteLine($"Error initializing RemoteWebDriver: {ex.Message}");
}
attempt++;
} while (attempt < maxAttempts);
// We will never get here. Keeping the compiler happy.
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is unresponsive");
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive");
}
}
}