Browse Source

Fix a memory leak.

Caused by not call SocketAsyncEventArgs.Dispose().
tags/3.3
noisyfox Syrone Wong 8 years ago
parent
commit
e364457b1b
2 changed files with 53 additions and 13 deletions
  1. +14
    -3
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  2. +39
    -10
      shadowsocks-csharp/Util/SocketUtil.cs

+ 14
- 3
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -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
shadowsocks-csharp/Util/SocketUtil.cs 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)


Loading…
Cancel
Save