Fix a memory leak.

Caused by not call SocketAsyncEventArgs.Dispose().
This commit is contained in:
noisyfox
2016-09-03 15:17:16 +08:00
committed by Syrone Wong
parent be85ab55a7
commit e364457b1b
2 changed files with 53 additions and 13 deletions
@@ -449,11 +449,17 @@ namespace Shadowsocks.Controller
private void proxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
{
var timer = (ProxyTimer) sender;
timer.Elapsed -= proxyConnectTimer_Elapsed;
timer.Enabled = false;
timer.Dispose();
if (_proxyConnected || _destConnected)
{
return;
}
var proxy = ((ProxyTimer)sender).Session.Remote;
var proxy = timer.Session.Remote;
Logging.Info($"Proxy {proxy.ProxyEndPoint} timed out");
proxy.Close();
@@ -516,13 +522,18 @@ namespace Shadowsocks.Controller
private void destConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
{
var timer = (ServerTimer)sender;
timer.Elapsed -= destConnectTimer_Elapsed;
timer.Enabled = false;
timer.Dispose();
if (_destConnected)
{
return;
}
var session = ((ServerTimer) sender).Session;
Server server = ((ServerTimer)sender).Server;
var session = timer.Session;
Server server = timer.Server;
IStrategy strategy = controller.GetCurrentStrategy();
strategy?.SetFailure(server);
Logging.Info($"{server.FriendlyName()} timed out");
+39 -10
View File
@@ -36,10 +36,27 @@ namespace Shadowsocks.Util
return new DnsEndPoint2(host, port);
}
private class TcpUserToken : IAsyncResult
private class AutoReleaseAsyncResult : IAsyncResult
{
public AsyncCallback Callback { get; }
public SocketAsyncEventArgs Args { get; }
public bool IsCompleted { get; } = true;
public WaitHandle AsyncWaitHandle { get; } = null;
public object AsyncState { get; set; }
public bool CompletedSynchronously { get; } = true;
public TcpUserToken UserToken { get; set; }
~AutoReleaseAsyncResult()
{
UserToken.Dispose();
}
}
private class TcpUserToken
{
public AsyncCallback Callback { get; private set; }
public SocketAsyncEventArgs Args { get; private set; }
public object AsyncState { get; private set; }
public TcpUserToken(AsyncCallback callback, object state, SocketAsyncEventArgs args)
{
@@ -48,17 +65,27 @@ namespace Shadowsocks.Util
Args = args;
}
public bool IsCompleted { get; } = true;
public WaitHandle AsyncWaitHandle { get; } = null;
public object AsyncState { get; }
public bool CompletedSynchronously { get; } = true;
public void Dispose()
{
Args?.Dispose();
Callback = null;
Args = null;
AsyncState = null;
}
}
private static void OnTcpConnectCompleted(object sender, SocketAsyncEventArgs args)
{
args.Completed -= OnTcpConnectCompleted;
TcpUserToken token = (TcpUserToken) args.UserToken;
token.Callback(token);
AutoReleaseAsyncResult r = new AutoReleaseAsyncResult
{
AsyncState = token.AsyncState,
UserToken = token
};
token.Callback(r);
}
public static void BeginConnectTcp(EndPoint endPoint, AsyncCallback callback, object state)
@@ -74,12 +101,14 @@ namespace Shadowsocks.Util
public static Socket EndConnectTcp(IAsyncResult asyncResult)
{
var tut = asyncResult as TcpUserToken;
if (tut == null)
var r = asyncResult as AutoReleaseAsyncResult;
if (r == null)
{
throw new ArgumentException("Invalid asyncResult.", nameof(asyncResult));
}
var tut = r.UserToken;
var arg = tut.Args;
if (arg.SocketError != SocketError.Success)