Unverified Commit 40c978d3 authored by justcoding121's avatar justcoding121 Committed by GitHub

Merge pull request #446 from justcoding121/master

Fix prefetch connection leak
parents 02ea4aec d0f53206
...@@ -150,8 +150,12 @@ namespace Titanium.Web.Proxy ...@@ -150,8 +150,12 @@ namespace Titanium.Web.Proxy
} }
SslStream sslStream = null; SslStream sslStream = null;
//don't pass cancellation token here
//it could cause floating server connections when client exits
prefetchConnectionTask = getServerConnection(connectArgs, true, prefetchConnectionTask = getServerConnection(connectArgs, true,
null, false, cancellationToken); null, false, CancellationToken.None);
try try
{ {
sslStream = new SslStream(clientStream); sslStream = new SslStream(clientStream);
...@@ -250,7 +254,7 @@ namespace Titanium.Web.Proxy ...@@ -250,7 +254,7 @@ namespace Titanium.Web.Proxy
{ {
await tcpConnectionFactory.Release(connection, true); await tcpConnectionFactory.Release(connection, true);
} }
calledRequestHandler = true;
return; return;
} }
} }
...@@ -331,18 +335,26 @@ namespace Titanium.Web.Proxy ...@@ -331,18 +335,26 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
clientStream.Dispose(); if (!calledRequestHandler
&& prefetchConnectionTask != null)
{
TcpServerConnection prefetchedConnection = null;
try
{
prefetchedConnection = await prefetchConnectionTask;
if (!cancellationTokenSource.IsCancellationRequested) }
finally
{ {
cancellationTokenSource.Cancel(); await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
}
} }
if (!calledRequestHandler clientStream.Dispose();
&& prefetchConnectionTask != null)
if (!cancellationTokenSource.IsCancellationRequested)
{ {
var connection = await prefetchConnectionTask; cancellationTokenSource.Cancel();
await tcpConnectionFactory.Release(connection, closeServerConnection);
} }
} }
} }
......
...@@ -815,12 +815,12 @@ namespace Titanium.Web.Proxy ...@@ -815,12 +815,12 @@ namespace Titanium.Web.Proxy
.RetryAsync(retries, .RetryAsync(retries,
onRetryAsync: async (ex, i, context) => onRetryAsync: async (ex, i, context) =>
{ {
if (context.ContainsKey("connection")) if (context["connection"] != null)
{ {
//close connection on error //close connection on error
var connection = (TcpServerConnection)context["connection"]; var connection = (TcpServerConnection)context["connection"];
await tcpConnectionFactory.Release(connection, true); await tcpConnectionFactory.Release(connection, true);
context.Remove("connection"); context["connection"] = null;
} }
}); });
......
...@@ -58,14 +58,14 @@ namespace Titanium.Web.Proxy ...@@ -58,14 +58,14 @@ namespace Titanium.Web.Proxy
CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest, CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest,
Task<TcpServerConnection> prefetchConnectionTask = null) Task<TcpServerConnection> prefetchConnectionTask = null)
{ {
var cancellationToken = cancellationTokenSource.Token;
var prefetchTask = prefetchConnectionTask; var prefetchTask = prefetchConnectionTask;
TcpServerConnection connection = null; TcpServerConnection connection = null;
bool closeServerConnection = false; bool closeServerConnection = false;
try try
{ {
var cancellationToken = cancellationTokenSource.Token;
// Loop through each subsequest request on this particular client connection // Loop through each subsequest request on this particular client connection
// (assuming HTTP connection is kept alive by client) // (assuming HTTP connection is kept alive by client)
while (true) while (true)
...@@ -204,19 +204,11 @@ namespace Titanium.Web.Proxy ...@@ -204,19 +204,11 @@ namespace Titanium.Web.Proxy
connection = null; connection = null;
} }
var contextData = new Dictionary<string, object>();
if (connection != null)
{
contextData.Add("connection", connection);
}
//for connection pool retry fails until cache is exhausted //for connection pool retry fails until cache is exhausted
await retryPolicy<ServerConnectionException>().ExecuteAsync(async (context) => await retryPolicy<ServerConnectionException>().ExecuteAsync(async (context) =>
{ {
connection = context["connection"] as TcpServerConnection ??
connection = context.ContainsKey("connection")? await getServerConnection(args, false,
(TcpServerConnection)context["connection"]
: await getServerConnection(args, false,
clientConnection.NegotiatedApplicationProtocol, clientConnection.NegotiatedApplicationProtocol,
false, cancellationToken); false, cancellationToken);
...@@ -235,8 +227,7 @@ namespace Titanium.Web.Proxy ...@@ -235,8 +227,7 @@ namespace Titanium.Web.Proxy
// construct the web request that we are going to issue on behalf of the client. // construct the web request that we are going to issue on behalf of the client.
await handleHttpSessionRequestInternal(connection, args); await handleHttpSessionRequestInternal(connection, args);
}, contextData); }, new Dictionary<string, object> { { "connection", connection } });
//user requested //user requested
if (args.WebSession.CloseServerConnection) if (args.WebSession.CloseServerConnection)
...@@ -290,10 +281,19 @@ namespace Titanium.Web.Proxy ...@@ -290,10 +281,19 @@ namespace Titanium.Web.Proxy
await tcpConnectionFactory.Release(connection, await tcpConnectionFactory.Release(connection,
closeServerConnection); closeServerConnection);
if (prefetchTask != null) if (prefetchTask != null)
{ {
await tcpConnectionFactory.Release(await prefetchTask, TcpServerConnection prefetchedConnection = null;
closeServerConnection); try
{
prefetchedConnection = await prefetchTask;
}
finally
{
await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
}
} }
} }
} }
......
...@@ -63,9 +63,11 @@ namespace Titanium.Web.Proxy ...@@ -63,9 +63,11 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl) if (endPoint.DecryptSsl && args.DecryptSsl)
{ {
//don't pass cancellation token here
//it could cause floating server connections when client exits
prefetchConnectionTask = tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port, prefetchConnectionTask = tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, true, null, false, this, null, true, null, false, this,
UpStreamEndPoint, UpStreamHttpsProxy, false, cancellationToken); UpStreamEndPoint, UpStreamHttpsProxy, false, CancellationToken.None);
SslStream sslStream = null; SslStream sslStream = null;
...@@ -163,8 +165,16 @@ namespace Titanium.Web.Proxy ...@@ -163,8 +165,16 @@ namespace Titanium.Web.Proxy
if (!calledRequestHandler if (!calledRequestHandler
&& prefetchConnectionTask != null) && prefetchConnectionTask != null)
{ {
var connection = await prefetchConnectionTask; TcpServerConnection prefetchedConnection = null;
await tcpConnectionFactory.Release(connection, closeServerConnection); try
{
prefetchedConnection = await prefetchConnectionTask;
}
finally
{
await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
}
} }
clientStream.Dispose(); clientStream.Dispose();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment