Skip to content

Update branding to 2.1.16 #18205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions eng/Baseline.Designer.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<AspNetCoreBaselineVersion>2.1.14</AspNetCoreBaselineVersion>
<AspNetCoreBaselineVersion>2.1.15</AspNetCoreBaselineVersion>
</PropertyGroup>
<!-- Package: dotnet-dev-certs-->
<PropertyGroup Condition=" '$(PackageId)' == 'dotnet-dev-certs' ">
Expand Down Expand Up @@ -453,25 +453,27 @@
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Http.Connections-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections' ">
<BaselinePackageVersion>1.0.4</BaselinePackageVersion>
<BaselinePackageVersion>1.0.15</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections' AND '$(TargetFramework)' == 'netcoreapp2.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Routing" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.WebSockets" Version="[2.1.1, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[11.0.2, )" />
<BaselinePackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="[4.5.3, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Routing" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.WebSockets" Version="[2.1.1, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[11.0.2, )" />
<BaselinePackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="[4.5.3, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Http.Extensions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Extensions' ">
Expand Down Expand Up @@ -1061,12 +1063,12 @@
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Core-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Core' ">
<BaselinePackageVersion>1.0.4</BaselinePackageVersion>
<BaselinePackageVersion>1.0.15</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Core' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[1.0.4, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[2.1.1, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.1.1, )" />
<BaselinePackageReference Include="System.Reflection.Emit" Version="[4.3.0, )" />
Expand Down
6 changes: 3 additions & 3 deletions eng/Baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file contains a list of all the packages and their versions which were rele
build of ASP.NET Core 2.1.x. Update this list when preparing for a new patch.

-->
<Baseline Version="2.1.14">
<Baseline Version="2.1.15">
<Package Id="dotnet-dev-certs" Version="2.1.1" />
<Package Id="dotnet-sql-cache" Version="2.1.1" />
<Package Id="dotnet-user-secrets" Version="2.1.1" />
Expand Down Expand Up @@ -53,7 +53,7 @@ build of ASP.NET Core 2.1.x. Update this list when preparing for a new patch.
<Package Id="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.1" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Common" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.Http.Connections" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.Http.Connections" Version="1.0.15" />
<Package Id="Microsoft.AspNetCore.Http.Extensions" Version="2.1.1" />
<Package Id="Microsoft.AspNetCore.Http.Features" Version="2.1.1" />
<Package Id="Microsoft.AspNetCore.Http" Version="2.1.1" />
Expand Down Expand Up @@ -109,7 +109,7 @@ build of ASP.NET Core 2.1.x. Update this list when preparing for a new patch.
<Package Id="Microsoft.AspNetCore.SignalR.Client.Core" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.SignalR.Client" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.SignalR.Common" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.SignalR.Core" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.SignalR.Core" Version="1.0.15" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="1.0.4" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.0.11" />
<Package Id="Microsoft.AspNetCore.SignalR.Redis" Version="1.0.11" />
Expand Down
4 changes: 3 additions & 1 deletion eng/PatchConfig.props
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ Later on, this will be checked using this condition:
Microsoft.AspNetCore.CookiePolicy;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.1.15' ">
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.1.16' ">
<PackagesInPatch>
Microsoft.AspNetCore.Http.Connections;
Microsoft.AspNetCore.SignalR.Core;
</PackagesInPatch>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

23 changes: 22 additions & 1 deletion src/SignalR/clients/ts/FunctionalTests/selenium/run-tests.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { ChildProcess, spawn } from "child_process";
import * as fs from "fs";
import * as _fs from "fs";
import { EOL } from "os";
import * as path from "path";
import { promisify } from "util";
import { PassThrough, Readable } from "stream";

import { run } from "../../webdriver-tap-runner/lib";

import * as _debug from "debug";
const debug = _debug("signalr-functional-tests:run");

const ARTIFACTS_DIR = path.resolve(__dirname, "..", "..", "..", "..", "artifacts");
const LOGS_DIR = path.resolve(ARTIFACTS_DIR, "logs");

// Promisify things from fs we want to use.
const fs = {
createWriteStream: _fs.createWriteStream,
exists: promisify(_fs.exists),
mkdir: promisify(_fs.mkdir),
};

process.on("unhandledRejection", (reason) => {
console.error(`Unhandled promise rejection: ${reason}`);
process.exit(1);
Expand Down Expand Up @@ -102,6 +113,13 @@ if (chromePath) {
try {
const serverPath = path.resolve(__dirname, "..", "bin", configuration, "netcoreapp2.1", "FunctionalTests.dll");

if (!await fs.exists(ARTIFACTS_DIR)) {
await fs.mkdir(ARTIFACTS_DIR);
}
if (!await fs.exists(LOGS_DIR)) {
await fs.mkdir(LOGS_DIR);
}

debug(`Launching Functional Test Server: ${serverPath}`);
const dotnet = spawn("dotnet", [serverPath], {
env: {
Expand All @@ -117,6 +135,9 @@ if (chromePath) {
}
}

const logStream = fs.createWriteStream(path.resolve(LOGS_DIR, "ts.functionaltests.dotnet.log"));
dotnet.stdout.pipe(logStream);

process.on("SIGINT", cleanup);
process.on("exit", cleanup);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class HttpConnectionContext : ConnectionContext,
IHttpTransportFeature,
IConnectionInherentKeepAliveFeature
{
private static long _tenSeconds = TimeSpan.FromSeconds(10).Ticks;

private readonly object _itemsLock = new object();
private readonly object _heartbeatLock = new object();
private List<(Action<object> handler, object state)> _heartbeatHandlers;
Expand All @@ -35,6 +37,13 @@ public class HttpConnectionContext : ConnectionContext,
private IDuplexPipe _application;
private IDictionary<object, object> _items;

private CancellationTokenSource _sendCts;
private bool _activeSend;
private long _startedSendTime;
private readonly object _sendingLock = new object();

internal CancellationToken SendingToken { get; private set; }

// This tcs exists so that multiple calls to DisposeAsync all wait asynchronously
// on the same task
private readonly TaskCompletionSource<object> _disposeTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
Expand Down Expand Up @@ -274,24 +283,45 @@ private async Task WaitOnTasks(Task applicationTask, Task transportTask, bool cl
// Cancel any pending flushes from back pressure
Application?.Output.CancelPendingFlush();

// Shutdown both sides and wait for nothing
Transport?.Output.Complete(applicationTask.Exception?.InnerException);
Application?.Output.Complete(transportTask.Exception?.InnerException);

// Normally it isn't safe to try and acquire this lock because the Send can hold onto it for a long time if there is backpressure
// It is safe to wait for this lock now because the Send will be in one of 4 states
// 1. In the middle of a write which is in the middle of being canceled by the CancelPendingFlush above, when it throws
// an OperationCanceledException it will complete the PipeWriter which will make any other Send waiting on the lock
// throw an InvalidOperationException if they call Write
// 2. About to write and see that there is a pending cancel from the CancelPendingFlush, go to 1 to see what happens
// 3. Enters the Send and sees the Dispose state from DisposeAndRemoveAsync and releases the lock
// 4. No Send in progress
await WriteLock.WaitAsync();
try
{
Log.WaitingForTransportAndApplication(_logger, TransportType);
// A poorly written application *could* in theory get stuck forever and it'll show up as a memory leak
await Task.WhenAll(applicationTask, transportTask);
// Complete the applications read loop
Application?.Output.Complete(transportTask.Exception?.InnerException);
}
finally
{
Log.TransportAndApplicationComplete(_logger, TransportType);

// Close the reading side after both sides run
Application?.Input.Complete();
Transport?.Input.Complete();
WriteLock.Release();
}

Application?.Input.CancelPendingRead();

await transportTask.NoThrow();
Application?.Input.Complete();

Log.WaitingForTransportAndApplication(_logger, TransportType);

// A poorly written application *could* in theory get stuck forever and it'll show up as a memory leak
// Wait for application so we can complete the writer safely
await applicationTask.NoThrow();
Log.TransportAndApplicationComplete(_logger, TransportType);

// Shutdown application side now that it's finished
Transport?.Output.Complete(applicationTask.Exception?.InnerException);

// Close the reading side after both sides run
Transport?.Input.Complete();

// Observe exceptions
await Task.WhenAll(transportTask, applicationTask);
}

// Notify all waiters that we're done disposing
Expand All @@ -311,6 +341,43 @@ private async Task WaitOnTasks(Task applicationTask, Task transportTask, bool cl
}
}

internal void StartSendCancellation()
{
lock (_sendingLock)
{
if (_sendCts == null || _sendCts.IsCancellationRequested)
{
_sendCts = new CancellationTokenSource();
SendingToken = _sendCts.Token;
}

_startedSendTime = DateTime.UtcNow.Ticks;
_activeSend = true;
}
}

internal void TryCancelSend(long currentTicks)
{
lock (_sendingLock)
{
if (_activeSend)
{
if (currentTicks - _startedSendTime > _tenSeconds)
{
_sendCts.Cancel();
}
}
}
}

internal void StopSendCancellation()
{
lock (_sendingLock)
{
_activeSend = false;
}
}

private static class Log
{
private static readonly Action<ILogger, string, Exception> _disposingConnection =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti
connection.SupportedFormats = TransferFormat.Text;

// We only need to provide the Input channel since writing to the application is handled through /send.
var sse = new ServerSentEventsTransport(connection.Application.Input, connection.ConnectionId, _loggerFactory);
var sse = new ServerSentEventsTransport(connection.Application.Input, connection.ConnectionId, connection, _loggerFactory);

await DoPersistentConnection(connectionDelegate, sse, context, connection);
}
Expand Down Expand Up @@ -264,7 +264,7 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti
context.Response.RegisterForDispose(timeoutSource);
context.Response.RegisterForDispose(tokenSource);

var longPolling = new LongPollingTransport(timeoutSource.Token, connection.Application.Input, _loggerFactory);
var longPolling = new LongPollingTransport(timeoutSource.Token, connection.Application.Input, _loggerFactory, connection);

// Start the transport
connection.TransportTask = longPolling.ProcessRequestAsync(context, tokenSource.Token);
Expand All @@ -291,7 +291,9 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti
connection.Transport.Output.Complete(connection.ApplicationTask.Exception);

// Wait for the transport to run
await connection.TransportTask;
// Ignore exceptions, it has been logged if there is one and the application has finished
// So there is no one to give the exception to
await connection.TransportTask.NoThrow();

// If the status code is a 204 it means the connection is done
if (context.Response.StatusCode == StatusCodes.Status204NoContent)
Expand All @@ -307,6 +309,18 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti
pollAgain = false;
}
}
else if (connection.TransportTask.IsFaulted || connection.TransportTask.IsCanceled)
{
// Cancel current request to release any waiting poll and let dispose aquire the lock
currentRequestTcs.TrySetCanceled();

// We should be able to safely dispose because there's no more data being written
// We don't need to wait for close here since we've already waited for both sides
await _manager.DisposeAndRemoveAsync(connection, closeGracefully: false);

// Don't poll again if we've removed the connection completely
pollAgain = false;
}
else if (context.Response.StatusCode == StatusCodes.Status204NoContent)
{
// Don't poll if the transport task was canceled
Expand Down Expand Up @@ -511,6 +525,14 @@ private async Task ProcessSend(HttpContext context, HttpConnectionDispatcherOpti

context.Response.StatusCode = StatusCodes.Status404NotFound;
context.Response.ContentType = "text/plain";

// There are no writes anymore (since this is the write "loop")
// So it is safe to complete the writer
// We complete the writer here because we already have the WriteLock acquired
// and it's unsafe to complete outside of the lock
// Other code isn't guaranteed to be able to acquire the lock before another write
// even if CancelPendingFlush is called, and the other write could hang if there is backpressure
connection.Application.Output.Complete();
return;
}

Expand Down Expand Up @@ -549,11 +571,8 @@ private async Task ProcessDeleteAsync(HttpContext context)

Log.TerminatingConection(_logger);

// Complete the receiving end of the pipe
connection.Application.Output.Complete();

// Dispose the connection gracefully, but don't wait for it. We assign it here so we can wait in tests
connection.DisposeAndRemoveTask = _manager.DisposeAndRemoveAsync(connection, closeGracefully: true);
// Dispose the connection, but don't wait for it. We assign it here so we can wait in tests
connection.DisposeAndRemoveTask = _manager.DisposeAndRemoveAsync(connection, closeGracefully: false);

context.Response.StatusCode = StatusCodes.Status202Accepted;
context.Response.ContentType = "text/plain";
Expand Down
Loading