Selaa lähdekoodia

Avoid holding WebRequest. This should fix part of bug #636500.

Atsushi Eno 15 vuotta sitten
vanhempi
sitoutus
59de000b20

+ 27 - 14
mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpRequestChannel.cs

@@ -41,7 +41,7 @@ namespace System.ServiceModel.Channels
 	{
 		HttpChannelFactory<IRequestChannel> source;
 
-		WebRequest web_request;
+		List<WebRequest> web_requests = new List<WebRequest> ();
 
 		// Constructor
 
@@ -76,7 +76,9 @@ namespace System.ServiceModel.Channels
 				 	destination = Via ?? RemoteAddress.Uri;
 			}
 
-			web_request = HttpWebRequest.Create (destination);
+			var web_request = HttpWebRequest.Create (destination);
+			web_requests.Add (web_request);
+			result.WebRequest = web_request;
 			web_request.Method = "POST";
 			web_request.ContentType = Encoder.ContentType;
 
@@ -192,7 +194,7 @@ namespace System.ServiceModel.Channels
 			WebResponse res;
 			Stream resstr;
 			try {
-				res = web_request.EndGetResponse (result);
+				res = channelResult.WebRequest.EndGetResponse (result);
 				resstr = res.GetResponseStream ();
 			} catch (WebException we) {
 				res = we.Response;
@@ -259,7 +261,7 @@ namespace System.ServiceModel.Channels
 		{
 			ThrowIfDisposedOrNotOpen ();
 
-			HttpChannelRequestAsyncResult result = new HttpChannelRequestAsyncResult (message, timeout, callback, state);
+			HttpChannelRequestAsyncResult result = new HttpChannelRequestAsyncResult (message, timeout, this, callback, state);
 			BeginProcessRequest (result);
 			return result;
 		}
@@ -279,25 +281,21 @@ namespace System.ServiceModel.Channels
 
 		protected override void OnAbort ()
 		{
-			if (web_request != null)
+			foreach (var web_request in web_requests)
 				web_request.Abort ();
-			web_request = null;
+			web_requests.Clear ();
 		}
 
 		// Close
 
 		protected override void OnClose (TimeSpan timeout)
 		{
-			if (web_request != null)
-				web_request.Abort ();
-			web_request = null;
+			OnAbort ();
 		}
 
 		protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
 		{
-			if (web_request != null)
-				web_request.Abort ();
-			web_request = null;
+			OnAbort ();
 			return base.OnBeginClose (timeout, callback, state);
 		}
 
@@ -324,7 +322,7 @@ namespace System.ServiceModel.Channels
 			base.OnEndOpen (result);
 		}
 
-		class HttpChannelRequestAsyncResult : IAsyncResult
+		class HttpChannelRequestAsyncResult : IAsyncResult, IDisposable
 		{
 			public Message Message {
 				get; private set;
@@ -339,11 +337,13 @@ namespace System.ServiceModel.Channels
 			Exception error;
 			object locker = new object ();
 			bool is_completed;
+			HttpRequestChannel owner;
 
-			public HttpChannelRequestAsyncResult (Message message, TimeSpan timeout, AsyncCallback callback, object state)
+			public HttpChannelRequestAsyncResult (Message message, TimeSpan timeout, HttpRequestChannel owner, AsyncCallback callback, object state)
 			{
 				Message = message;
 				Timeout = timeout;
+				this.owner = owner;
 				this.callback = callback;
 				AsyncState = state;
 			}
@@ -352,6 +352,8 @@ namespace System.ServiceModel.Channels
 				get; set;
 			}
 
+			public WebRequest WebRequest { get; set; }
+
 			public WaitHandle AsyncWaitHandle {
 				get {
 					lock (locker) {
@@ -395,6 +397,7 @@ namespace System.ServiceModel.Channels
 					lock (locker) {
 						if (is_completed && wait != null)
 							wait.Set ();
+						Cleanup ();
 					}
 				}
 			}
@@ -417,6 +420,16 @@ namespace System.ServiceModel.Channels
 				if (error != null)
 					throw error;
 			}
+			
+			public void Dispose ()
+			{
+				Cleanup ();
+			}
+			
+			void Cleanup ()
+			{
+				owner.web_requests.Remove (WebRequest);
+			}
 		}
 	}
 }