Fix a memory leak.
Caused by not call SocketAsyncEventArgs.Dispose().
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user